<!DOCTYPE HTML>
<html lang="zh-CN">


<head>
    <!-- hexo-inject:begin --><!-- hexo-inject:end --><meta charset="utf-8">
    <meta name="keywords" content="VueJS, HTML,CSS,JavaScript,JQuery,React,Vue.js等">
    <meta name="description" content="别做一个Vue api调用师">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
    <meta name="renderer" content="webkit|ie-stand|ie-comp">
    <meta name="mobile-web-app-capable" content="yes">
    <meta name="format-detection" content="telephone=no">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
    <!-- Global site tag (gtag.js) - Google Analytics -->


    <title>VueJS | zihao blog</title>
    <link rel="icon" type="image/png" href="/pride-blog/favicon.png">

    <link rel="stylesheet" type="text/css" href="/pride-blog/libs/awesome/css/all.css">
    <link rel="stylesheet" type="text/css" href="/pride-blog/libs/materialize/materialize.min.css">
    <link rel="stylesheet" type="text/css" href="/pride-blog/libs/aos/aos.css">
    <link rel="stylesheet" type="text/css" href="/pride-blog/libs/animate/animate.min.css">
    <link rel="stylesheet" type="text/css" href="/pride-blog/libs/lightGallery/css/lightgallery.min.css">
    <link rel="stylesheet" type="text/css" href="/pride-blog/css/matery.css">
    <link rel="stylesheet" type="text/css" href="/pride-blog/css/my.css">

    <script src="/pride-blog/libs/jquery/jquery.min.js"></script>

<meta name="generator" content="Hexo 5.3.0"><link rel="stylesheet" href="/pride-blog/css/prism-tomorrow.css" type="text/css"><!-- hexo-inject:begin --><!-- hexo-inject:end --></head>




<body>
    <!-- hexo-inject:begin --><!-- hexo-inject:end --><header class="navbar-fixed">
    <nav id="headNav" class="bg-color nav-transparent">
        <div id="navContainer" class="nav-wrapper container">
            <div class="brand-logo">
                <a href="/pride-blog/" class="waves-effect waves-light">
                    
                    <img src="/pride-blog/medias/logo.png" class="logo-img" alt="LOGO">
                    
                    <span class="logo-span">zihao blog</span>
                </a>
            </div>
            

<a href="#" data-target="mobile-nav" class="sidenav-trigger button-collapse"><i class="fas fa-bars"></i></a>
<ul class="right nav-menu">
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/pride-blog/" class="waves-effect waves-light">
      
      <i class="fas fa-home" style="zoom: 0.6;"></i>
      
      <span>首页</span>
    </a>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/pride-blog/categories/CSS/" class="waves-effect waves-light">
      
      <i class="fas fa-bookmark" style="zoom: 0.6;"></i>
      
      <span>分类</span>
    </a>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/pride-blog/archives" class="waves-effect waves-light">
      
      <i class="fas fa-archive" style="zoom: 0.6;"></i>
      
      <span>归档</span>
    </a>
    
  </li>
  
  <li>
    <a href="#searchModal" class="modal-trigger waves-effect waves-light">
      <i id="searchIcon" class="fas fa-search" title="搜索" style="zoom: 0.85;"></i>
    </a>
  </li>
</ul>


<div id="mobile-nav" class="side-nav sidenav">

    <div class="mobile-head bg-color">
        
        <img src="/pride-blog/medias/logo.png" class="logo-img circle responsive-img">
        
        <div class="logo-name">zihao blog</div>
        <div class="logo-desc">
            
            别做一个Vue api调用师
            
        </div>
    </div>

    

    <ul class="menu-list mobile-menu-list">
        
        <li class="m-nav-item">
	  
		<a href="/pride-blog/" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-home"></i>
			
			首页
		</a>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="/pride-blog/categories/CSS/" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-bookmark"></i>
			
			分类
		</a>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="/pride-blog/archives" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-archive"></i>
			
			归档
		</a>
          
        </li>
        
        
    </ul>
</div>


        </div>

        
    </nav>

</header>

    



<div class="bg-cover pd-header post-cover" style="background-image: url('/pride-blog/medias/featureimages/23.jpg')">
    <div class="container" style="right: 0px;left: 0px;">
        <div class="row">
            <div class="col s12 m12 l12">
                <div class="brand">
                    <h1 class="description center-align post-title">VueJS</h1>
                </div>
            </div>
        </div>
    </div>
</div>




<main class="post-container content">

    
    <link rel="stylesheet" href="/pride-blog/libs/tocbot/tocbot.css">
<style>
    #articleContent h1::before,
    #articleContent h2::before,
    #articleContent h3::before,
    #articleContent h4::before,
    #articleContent h5::before,
    #articleContent h6::before {
        display: block;
        content: " ";
        height: 100px;
        margin-top: -100px;
        visibility: hidden;
    }

    #articleContent :focus {
        outline: none;
    }

    .toc-fixed {
        position: fixed;
        top: 64px;
    }

    .toc-widget {
        width: 345px;
        padding-left: 20px;
    }

    .toc-widget .toc-title {
        padding: 35px 0 15px 17px;
        font-size: 1.5rem;
        font-weight: bold;
        line-height: 1.5rem;
    }

    .toc-widget ol {
        padding: 0;
        list-style: none;
    }

    #toc-content {
        padding-bottom: 30px;
        overflow: auto;
    }

    #toc-content ol {
        padding-left: 10px;
    }

    #toc-content ol li {
        padding-left: 10px;
    }

    #toc-content .toc-link:hover {
        color: #42b983;
        font-weight: 700;
        text-decoration: underline;
    }

    #toc-content .toc-link::before {
        background-color: transparent;
        max-height: 25px;

        position: absolute;
        right: 23.5vw;
        display: block;
    }

    #toc-content .is-active-link {
        color: #42b983;
    }

    #floating-toc-btn {
        position: fixed;
        right: 15px;
        bottom: 76px;
        padding-top: 15px;
        margin-bottom: 0;
        z-index: 998;
    }

    #floating-toc-btn .btn-floating {
        width: 48px;
        height: 48px;
    }

    #floating-toc-btn .btn-floating i {
        line-height: 48px;
        font-size: 1.4rem;
    }
</style>
<div class="row">
    <div id="main-content" class="col s12 m12 l9">
        <!-- 文章内容详情 -->
<div id="artDetail">
    <div class="card">
        <div class="card-content article-info">
            <div class="row tag-cate">
                <div class="col s7">
                    
                    <div class="article-tag">
                        
                            <a href="/pride-blog/tags/%E6%AF%8F%E5%A4%A9%E4%B8%80%E4%B8%AA%E7%A6%BB%E8%81%8C%E5%B0%8F%E6%8A%80%E5%B7%A7/">
                                <span class="chip bg-color">每天一个离职小技巧</span>
                            </a>
                        
                    </div>
                    
                </div>
                <div class="col s5 right-align">
                    
                    <div class="post-cate">
                        <i class="fas fa-bookmark fa-fw icon-category"></i>
                        
                            <a href="/pride-blog/categories/%E6%AF%8F%E5%A4%A9%E4%B8%80%E4%B8%AA%E7%A6%BB%E8%81%8C%E5%B0%8F%E6%8A%80%E5%B7%A7/" class="post-category">
                                每天一个离职小技巧
                            </a>
                        
                    </div>
                    
                </div>
            </div>

            <div class="post-info">
                
                <div class="post-date info-break-policy">
                    <i class="far fa-calendar-minus fa-fw"></i>发布日期:&nbsp;&nbsp;
                    2021-08-04
                </div>
                

                

                

                

                
            </div>
        </div>
        <hr class="clearfix">

        

        

        <div class="card-content article-card-content">
            <div id="articleContent">
                <h4 id="1-vue优点？"><a href="#1-vue优点？" class="headerlink" title="1.vue优点？"></a>1.<code>vue</code>优点？</h4><h4 id="轻量级框架："><a href="#轻量级框架：" class="headerlink" title="轻量级框架："></a>轻量级框架：</h4><p>只关注视图层，是一个构建数据的视图集合，大小只有几十 kb；</p>
<h4 id="简单易学："><a href="#简单易学：" class="headerlink" title="简单易学："></a>简单易学：</h4><p>国人开发，中文文档，不存在语言障碍 ，易于理解和学习； 双向</p>
<h4 id="数据绑定："><a href="#数据绑定：" class="headerlink" title="数据绑定："></a>数据绑定：</h4><p>保留了 angular 的特点，在数据操作方面更为简单；</p>
<h4 id="组件化："><a href="#组件化：" class="headerlink" title="组件化："></a>组件化：</h4><p>保留了 react 的优点，实现了 html 的封装和重用，在构建单页面应用方面有着独特的优势；<br>视图，数据，结构分离：<br>使数据的更改更为简单，不需要进行逻辑代码的修改，只需要操作数据就能完成相关操作；</p>
<h4 id="虚拟-DOM："><a href="#虚拟-DOM：" class="headerlink" title="虚拟 DOM："></a>虚拟 DOM：</h4><p>dom 操作是非常耗费性能的， 不再使用原生的 dom 操作节点，极大解放 dom 操作，但具体操作的还是 dom 不过是换了另一种方式；<br>运行速度更快:<br>相比较与 react 而言，同样是操作虚拟 dom，就性能而言，vue 存在很大的优势。</p>
<h4 id="2-vue父组件向子组件传递数据？"><a href="#2-vue父组件向子组件传递数据？" class="headerlink" title="2.vue父组件向子组件传递数据？"></a>2.<code>vue</code>父组件向子组件传递数据？</h4><p>1.通过<code>props</code></p>
<p>2.通过父组件　//触发子组件方法，并传参</p>
<pre><code>this.$refs.mychild.init(&quot;chrchr&quot;,&quot;120&quot;);</code></pre>
<h4 id="3-子组件向父组件传递事件"><a href="#3-子组件向父组件传递事件" class="headerlink" title="3.子组件向父组件传递事件?"></a>3.子组件向父组件传递事件?</h4><h3 id="emit-方法"><a href="#emit-方法" class="headerlink" title="$emit 方法"></a>$emit 方法</h3><h4 id="自定义子组件"><a href="#自定义子组件" class="headerlink" title="自定义子组件"></a>自定义子组件</h4><pre class=" language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>template</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>container<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span> <span class="token attr-name">@click</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>clickAction<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token entity" title="&#123;">&amp;#123;</span><span class="token entity" title="&#123;">&amp;#123;</span>titleName<span class="token entity" title="&#125;">&amp;#125;</span><span class="token entity" title="&#125;">&amp;#125;</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>line<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>template</span><span class="token punctuation">></span></span></code></pre>
<pre class=" language-javascript"><code class="language-javascript"><span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
  name<span class="token punctuation">:</span> <span class="token string">"HelloWorld"</span><span class="token punctuation">,</span>
  props<span class="token punctuation">:</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    titleName<span class="token punctuation">:</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
      type<span class="token punctuation">:</span> string<span class="token punctuation">,</span>
      <span class="token keyword">default</span><span class="token punctuation">:</span> <span class="token string">""</span><span class="token punctuation">,</span>
    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">,</span>
  <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">,</span>
  methods<span class="token punctuation">:</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    <span class="token function">clickAction</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
      <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">$emit</span><span class="token punctuation">(</span><span class="token string">"clickChild"</span><span class="token punctuation">,</span> <span class="token keyword">this</span><span class="token punctuation">.</span>titleName<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">,</span>
  <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">,</span>
<span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">;</span></code></pre>
<h4 id="父组件中调用子组件"><a href="#父组件中调用子组件" class="headerlink" title="父组件中调用子组件"></a>父组件中调用子组件</h4><pre class=" language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>message<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>ActivityHead</span> <span class="token attr-name">:titleName</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>msgRight<span class="token punctuation">"</span></span> <span class="token attr-name">@clickChild</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>clickChild<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>ActivityHead</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span></code></pre>
<pre class=" language-javascript"><code class="language-javascript"><span class="token keyword">import</span> ActivityHead <span class="token keyword">from</span> <span class="token string">"./ActivityHead.vue"</span><span class="token punctuation">;</span>
<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
  name<span class="token punctuation">:</span> <span class="token string">"HelloWorld"</span><span class="token punctuation">,</span>
  components<span class="token punctuation">:</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    ActivityHead<span class="token punctuation">,</span>
  <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">,</span>
  methods<span class="token punctuation">:</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    <span class="token function">clickChild</span><span class="token punctuation">(</span>msg<span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
      console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>msg<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">,</span>
  <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">,</span>
<span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">;</span></code></pre>
<h4 id="4-v-if与v-show的区别"><a href="#4-v-if与v-show的区别" class="headerlink" title="4.v-if与v-show的区别"></a>4.<code>v-if</code>与<code>v-show</code>的区别</h4><h4 id="共同点："><a href="#共同点：" class="headerlink" title="共同点："></a>共同点：</h4><p>都能控制元素的显示和隐藏；</p>
<h4 id="不同点："><a href="#不同点：" class="headerlink" title="不同点："></a>不同点：</h4><p>实现本质方法不同，v-show 本质就是通过控制 css 中的 display 设置为 none，控制隐藏，只会编译一次；v-if 是动态的向 DOM 树内添加或者删除 DOM 元素，若初始值为 false，就不会编译了。</p>
<p>而且 v-if 不停的销毁和创建比较消耗性能。 总结：如果要频繁切换某节点，使用 v-show(切换开销比较小，初始开销较大)。</p>
<p>如果不需要频繁切换某节点使用 v-if（初始渲染开销较小，切换开销比较大）。</p>
<h4 id="5-v-if-与-v-for的优先级"><a href="#5-v-if-与-v-for的优先级" class="headerlink" title="5.v-if 与 v-for的优先级?"></a>5.<code>v-if</code> 与 <code>v-for</code>的优先级?</h4><h4 id="核心答案："><a href="#核心答案：" class="headerlink" title="核心答案："></a>核心答案：</h4><p>1、v-for 优先于 v-if 被解析<br>2、如果同时出现，每次渲染都会先执行循环再判断条件，无论如何循环都不可避免，浪费了性能<br>3、要避免出现这种情况，则在外层嵌套 template，在这一层进行 v-if 判断，然后在内部进行 v-for 循环<br>4、如果条件出现在循环内部，可通过计算属性提前过滤掉那些不需要显示的项</p>
<h4 id="6-vue组件中data为什么必须是一个函数？"><a href="#6-vue组件中data为什么必须是一个函数？" class="headerlink" title="6.vue组件中data为什么必须是一个函数？"></a>6.<code>vue</code>组件中<code>data</code>为什么必须是一个函数？</h4><p>如果<code>data</code>是一个函数的话，这样每复用一次组件，就会返回一份新的<code>data</code>，类似于给每个组件实例创建一个私有的数据空间，让各个组件实例维护各自的数据。</p>
<p>而单纯的写成对象形式，就使得所有组件实例共用了一份<code>data</code>，就会造成一个变了全都会变的结果。</p>
<p>所以说<code>vue</code>组件的<code>data</code>必须是函数。这都是因为<code>js</code>的特性带来的，跟 vue 本身设计无关。</p>
<p><code>js</code>本身的面向对象编程也是基于原型链和构造函数，应该会注意原型链上添加一般都是一个函数方法而不会去添加一个对象了。</p>
<h4 id="7-VueX之actions与mutations的区别"><a href="#7-VueX之actions与mutations的区别" class="headerlink" title="7.VueX之actions与mutations的区别?"></a>7.<code>VueX</code>之<code>actions</code>与<code>mutations</code>的区别?</h4><h4 id="actions"><a href="#actions" class="headerlink" title="actions"></a>actions</h4><p>1、用于通过提交 mutation 改变数据</p>
<p>2、会默认将自身封装为一个<code>Promise</code></p>
<p>3、可以包含任意的异步操作</p>
<h4 id="mutations"><a href="#mutations" class="headerlink" title="mutations"></a>mutations</h4><p>1、通过提交<code>commit</code>改变数据</p>
<p>2、只是一个单纯的函数</p>
<p>3、不要使用异步操作，异步操作会导致变量不能追踪</p>
<p><img src="https://imgconvert.csdnimg.cn/aHR0cHM6Ly92dWV4LnZ1ZWpzLm9yZy92dWV4LnBuZw?x-oss-process=image/format,png"></p>
<h4 id="2-如何在-vuex-中使用异步修改"><a href="#2-如何在-vuex-中使用异步修改" class="headerlink" title="2.如何在 vuex 中使用异步修改?"></a>2.如何在 vuex 中使用异步修改?</h4><p>在调用<code>vuex</code>中的方法<code>action</code>的时候，用<code>promise</code>实现异步修改</p>
<pre class=" language-JAVASCRIPT"><code class="language-JAVASCRIPT">const actions = &#123;
    asyncLogin(&#123; commit &#125;, n)&#123;
        return new Promise(resolve => &#123;
            setTimeout(() => &#123;
                commit(types.UserLogin, n);
                resolve();
            &#125;,3000)
        &#125;)
    &#125;
&#125;</code></pre>
<h4 id="8-Vue有哪些组件间的通信方式"><a href="#8-Vue有哪些组件间的通信方式" class="headerlink" title="8.Vue有哪些组件间的通信方式?"></a>8.<code>Vue</code>有哪些组件间的通信方式?</h4><h3 id="核心答案：-1"><a href="#核心答案：-1" class="headerlink" title="核心答案："></a>核心答案：</h3><blockquote>
<p>Vue 组件间通信只要指以下 3 类通信：<br>父子组件通信、隔代组件通信、兄弟组件通信，下面我们分别介绍每种通信方式且会说明此种方法可适用于哪类组件间通信。</p>
</blockquote>
<h3 id="方法一"><a href="#方法一" class="headerlink" title="方法一"></a>方法一</h3><pre class=" language-javaScript"><code class="language-javaScript">props / $emit;</code></pre>
<p>父组件<code>A</code>通过<code>props</code>的方式向子组件<code>B</code>传递，<code>B to A</code> 通过在 B 组件中 <code>$emit</code>, <code>A</code> 组件中 <code>v-on</code> 的方式实现。</p>
<h4 id="1-父组件向子组件传值"><a href="#1-父组件向子组件传值" class="headerlink" title="1.父组件向子组件传值"></a>1.父组件向子组件传值</h4><p>接下来我们通过一个例子，说明父组件如何向子组件传递值：在子组件 Users.vue 中如何获取父组件 App.vue 中的数据</p>
<pre class=" language-javaScript"><code class="language-javaScript">userList: ["Henry", "Bucky", "Emily"];</code></pre>
<pre class=" language-html"><code class="language-html">//App.vue父组件
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>template</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>app<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>hook-users</span>
    <span class="token attr-name">:userList</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>userList<span class="token punctuation">"</span></span><span class="token punctuation">/></span></span>
    //前者自定义名称便于子组件调用，后者要传递数据名
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>template</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">></span></span>
import AppUsers from "./Components/AppUsers"
export default <span class="token entity" title="&#123;">&amp;#123;</span>
  name: 'App',
  data()<span class="token entity" title="&#123;">&amp;#123;</span>
    return<span class="token entity" title="&#123;">&amp;#123;</span>
      userList:["Henry","Bucky","Emily"]
    <span class="token entity" title="&#125;">&amp;#125;</span>
  <span class="token entity" title="&#125;">&amp;#125;</span>,
  components:<span class="token entity" title="&#123;">&amp;#123;</span>
    "app-users":AppUsers
  <span class="token entity" title="&#125;">&amp;#125;</span>
<span class="token entity" title="&#125;">&amp;#125;</span></code></pre>
<pre class=" language-html"><code class="language-html">//users子组件
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>template</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>hello<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>ul</span><span class="token punctuation">></span></span>
      //遍历传递过来的值，然后呈现到页面
      <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>li</span> <span class="token attr-name">v-for</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>user in userList<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token entity" title="&#123;">&amp;#123;</span><span class="token entity" title="&#123;">&amp;#123;</span>user<span class="token entity" title="&#125;">&amp;#125;</span><span class="token entity" title="&#125;">&amp;#125;</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>li</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>ul</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>template</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">></span></span><span class="token script language-javascript">
  <span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    name<span class="token punctuation">:</span> <span class="token string">"AppUsers"</span><span class="token punctuation">,</span>
    props<span class="token punctuation">:</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
      userList<span class="token punctuation">:</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
        type<span class="token punctuation">:</span> Array<span class="token punctuation">,</span>
        required<span class="token punctuation">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
      <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">,</span>
    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">,</span>
  <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">;</span>
</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">></span></span></code></pre>
<h4 id="总结："><a href="#总结：" class="headerlink" title="总结："></a>总结：</h4><p>父组件通过<code>props</code>向下传递数据给子组件。注：组件中的数据共有三种形式：<code>data</code>、<code>props</code>、<code>computed</code></p>
<h4 id="2-子组件向父组件传值（通过事件形式）"><a href="#2-子组件向父组件传值（通过事件形式）" class="headerlink" title="2.子组件向父组件传值（通过事件形式）"></a>2.子组件向父组件传值（通过事件形式）</h4><pre class=" language-html"><code class="language-html">// 子组件
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>template</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>header</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>h1</span> <span class="token attr-name">@click</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>changeTitle<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token entity" title="&#123;">&amp;#123;</span><span class="token entity" title="&#123;">&amp;#123;</span>title<span class="token entity" title="&#125;">&amp;#125;</span><span class="token entity" title="&#125;">&amp;#125;</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>h1</span><span class="token punctuation">></span></span>
    //绑定一个点击事件
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>header</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>template</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">></span></span><span class="token script language-javascript">
  <span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    name<span class="token punctuation">:</span> <span class="token string">"AppHeader"</span><span class="token punctuation">,</span>
    <span class="token function">data</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
      <span class="token keyword">return</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
        title<span class="token punctuation">:</span> <span class="token string">"Vue.js Demo"</span><span class="token punctuation">,</span>
      <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">;</span>
    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">,</span>
    methods<span class="token punctuation">:</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
      <span class="token function">changeTitle</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">$emit</span><span class="token punctuation">(</span><span class="token string">"titleChanged"</span><span class="token punctuation">,</span> <span class="token string">"子向父组件传值"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment" spellcheck="true">//自定义事件  传递值“子向父组件传值”</span>
      <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">,</span>
    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">,</span>
  <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">;</span>
</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">></span></span>

// 父组件
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>template</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>app<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>app-header</span> <span class="token attr-name"><span class="token namespace">v-on:</span>titleChanged</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>updateTitle<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>app-header</span><span class="token punctuation">></span></span>
    //与子组件titleChanged自定义事件保持一致 //
    updateTitle($event)接受传递过来的文字
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>h2</span><span class="token punctuation">></span></span><span class="token entity" title="&#123;">&amp;#123;</span><span class="token entity" title="&#123;">&amp;#123;</span>title<span class="token entity" title="&#125;">&amp;#125;</span><span class="token entity" title="&#125;">&amp;#125;</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>h2</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>template</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">></span></span><span class="token script language-javascript">
  <span class="token keyword">import</span> Header <span class="token keyword">from</span> <span class="token string">"./components/Header"</span><span class="token punctuation">;</span>
  <span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    name<span class="token punctuation">:</span> <span class="token string">"App"</span><span class="token punctuation">,</span>
    <span class="token function">data</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
      <span class="token keyword">return</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
        title<span class="token punctuation">:</span> <span class="token string">"传递的是一个值"</span><span class="token punctuation">,</span>
      <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">;</span>
    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">,</span>
    methods<span class="token punctuation">:</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
      <span class="token function">updateTitle</span><span class="token punctuation">(</span>e<span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
        <span class="token comment" spellcheck="true">//声明这个函数</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>title <span class="token operator">=</span> e<span class="token punctuation">;</span>
      <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">,</span>
    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">,</span>
    components<span class="token punctuation">:</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
      <span class="token string">"app-header"</span><span class="token punctuation">:</span> Header<span class="token punctuation">,</span>
    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">,</span>
  <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">;</span>
</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">></span></span></code></pre>
<h4 id="总结：-1"><a href="#总结：-1" class="headerlink" title="总结："></a>总结：</h4><p>子组件通过<code>events</code>给父组件发送消息，实际上就是子组件把自己的数据发送到父组件。</p>
<h3 id="方法二、-emit-on"><a href="#方法二、-emit-on" class="headerlink" title="方法二、$emit/$on"></a>方法二、$emit/$on</h3><p>这种方法通过一个空的<code>Vue</code>实例作为中央事件总线（事件中心），用它来触发事件和监听事件,巧妙而轻量地实现了任何组件间的通信，包括父子、兄弟、跨级。当我们的项目比较大时，可以选择更好的状态管理解决方案<code>vuex</code>。</p>
<p>1.具体实现方式：</p>
<pre class=" language-javascript"><code class="language-javascript"><span class="token keyword">var</span> App <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Vue</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
App<span class="token punctuation">.</span><span class="token function">$emit</span><span class="token punctuation">(</span>事件名<span class="token punctuation">,</span> 数据<span class="token punctuation">)</span><span class="token punctuation">;</span>
App<span class="token punctuation">.</span><span class="token function">$on</span><span class="token punctuation">(</span>事件名<span class="token punctuation">,</span> <span class="token punctuation">(</span>data<span class="token punctuation">)</span> <span class="token operator">=</span><span class="token operator">></span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span><span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>或者自己实现一个</p>
<pre class=" language-javascript"><code class="language-javascript"><span class="token keyword">class</span> <span class="token class-name">MyEventEmitter</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
  <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>event <span class="token operator">=</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span><span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">;</span>
  <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
  <span class="token comment" spellcheck="true">// 监听</span>
  <span class="token function">on</span><span class="token punctuation">(</span>type<span class="token punctuation">,</span> listener<span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>event<span class="token punctuation">[</span>type<span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
      <span class="token keyword">this</span><span class="token punctuation">.</span>event<span class="token punctuation">[</span>type<span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span>listener<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span> <span class="token keyword">else</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
      <span class="token keyword">this</span><span class="token punctuation">.</span>event<span class="token punctuation">[</span>type<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">[</span>listener<span class="token punctuation">]</span><span class="token punctuation">;</span>
    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
  <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
  <span class="token comment" spellcheck="true">//发送监听</span>
  <span class="token function">emit</span><span class="token punctuation">(</span>type<span class="token punctuation">,</span> <span class="token operator">...</span>rest<span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>event<span class="token punctuation">[</span>type<span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
      <span class="token keyword">this</span><span class="token punctuation">.</span>event<span class="token punctuation">[</span>type<span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span>fn<span class="token punctuation">)</span> <span class="token operator">=</span><span class="token operator">></span> fn<span class="token punctuation">.</span><span class="token function">apply</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">,</span> rest<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
  <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
  <span class="token comment" spellcheck="true">//移除监听器</span>
  <span class="token function">removeListener</span><span class="token punctuation">(</span>type<span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>event<span class="token punctuation">[</span>type<span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
      <span class="token keyword">delete</span> <span class="token keyword">this</span><span class="token punctuation">.</span>event<span class="token punctuation">[</span>type<span class="token punctuation">]</span><span class="token punctuation">;</span>
      console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>event<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
  <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
  <span class="token comment" spellcheck="true">//移除所有的监听器</span>
  <span class="token function">removeAllListener</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>event <span class="token operator">=</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span><span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">;</span>
  <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
<span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>

<span class="token keyword">var</span> MyEvent <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">MyEventEmitter</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
MyEvent<span class="token punctuation">.</span><span class="token function">$emit</span><span class="token punctuation">(</span>事件名<span class="token punctuation">,</span> 数据<span class="token punctuation">)</span><span class="token punctuation">;</span>
MyEvent<span class="token punctuation">.</span><span class="token function">$on</span><span class="token punctuation">(</span>事件名<span class="token punctuation">,</span> <span class="token punctuation">(</span>data<span class="token punctuation">)</span> <span class="token operator">=</span><span class="token operator">></span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span><span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<blockquote>
<p>但是这种方式，记得在每次触发监听的时候，记得移除上一个监听器</p>
</blockquote>
<h3 id="方法三、Vuex-与-localStorage"><a href="#方法三、Vuex-与-localStorage" class="headerlink" title="方法三、Vuex 与 localStorage"></a>方法三、Vuex 与 localStorage</h3><p>vuex 是 vue 的状态管理器，存储的数据是响应式的。但是并不会保存起来，刷新之后就回到了初始状态，具体做法应该在 vuex 里数据改变的时候把数据拷贝一份保存到 localStorage 里面，刷新之后，如果 localStorage 里有保存的数据，取出来再替换 store 里的 state。</p>
<pre class=" language-javascript"><code class="language-javascript"><span class="token keyword">const</span> jsonToString <span class="token operator">=</span> <span class="token punctuation">(</span>json<span class="token punctuation">)</span> <span class="token operator">=</span><span class="token operator">></span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
  <span class="token keyword">return</span> JSON<span class="token punctuation">.</span><span class="token function">stringify</span><span class="token punctuation">(</span>json<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">;</span>

<span class="token keyword">const</span> stringToJson <span class="token operator">=</span> <span class="token punctuation">(</span>keyName<span class="token punctuation">)</span> <span class="token operator">=</span><span class="token operator">></span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
  <span class="token comment" spellcheck="true">//暂不验证数据格式</span>
  <span class="token keyword">return</span> window<span class="token punctuation">.</span>localStorage<span class="token punctuation">.</span><span class="token function">getItem</span><span class="token punctuation">(</span>keyName<span class="token punctuation">)</span>
    <span class="token operator">?</span> JSON<span class="token punctuation">.</span><span class="token function">parse</span><span class="token punctuation">(</span>window<span class="token punctuation">.</span>localStorage<span class="token punctuation">.</span><span class="token function">getItem</span><span class="token punctuation">(</span>keyName<span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token punctuation">:</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span><span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">;</span>
<span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">;</span>
<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">new</span> <span class="token class-name">Vuex<span class="token punctuation">.</span>Store</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
  state<span class="token punctuation">:</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    selectCity<span class="token punctuation">:</span> <span class="token function">stringToJson</span><span class="token punctuation">(</span><span class="token string">"selectCity"</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
  <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">,</span>
  mutations<span class="token punctuation">:</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    <span class="token function">changeCity</span><span class="token punctuation">(</span>state<span class="token punctuation">,</span> selectCity<span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
      state<span class="token punctuation">.</span>selectCity <span class="token operator">=</span> selectCity<span class="token punctuation">;</span>
      <span class="token keyword">try</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
        window<span class="token punctuation">.</span>localStorage<span class="token punctuation">.</span><span class="token function">setItem</span><span class="token punctuation">(</span>
          <span class="token string">"selectCity"</span><span class="token punctuation">,</span>
          <span class="token function">jsonToString</span><span class="token punctuation">(</span>state<span class="token punctuation">.</span>selectCity<span class="token punctuation">)</span>
        <span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment" spellcheck="true">// 数据改变的时候把数据拷贝一份保存到localStorage里面</span>
      <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">e</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span><span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">,</span>
  <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">,</span>
<span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h3 id="方法四、-attrs-listeners"><a href="#方法四、-attrs-listeners" class="headerlink" title="方法四、$attrs/$listeners"></a>方法四、$attrs/$listeners</h3><h4 id="如图"><a href="#如图" class="headerlink" title="如图:"></a>如图:</h4><p><img src="https://yangyunhaiimagesoss.oss-cn-shanghai.aliyuncs.com/2009171600_1600329633808.png"></p>
<h4 id="场景"><a href="#场景" class="headerlink" title="场景"></a>场景</h4><p>有些变态需求：比如说 A 父组件里面导入了 B 组件，可是 B 组件里面又导入了 C 组件，现在需要 A 父组件传值给 C 组件，或者是 C 组件需要传值给父组件，这时候就需要用到$attrs和$listeners 了。</p>
<h4 id="attrs"><a href="#attrs" class="headerlink" title="$attrs"></a>$attrs</h4><p>包含了父作用域中不作为 prop 被识别 (且获取) 的特性绑定 (class 和 style 除外)。当一个组件没有声明任何 prop 时，这里会包含所有父作用域的绑定 (class 和 style 除外)，并且可以通过 v-bind=”$attrs” 传入内部组件——在创建高级别的组件时非常有用。（父传孙专用）</p>
<h4 id="listener"><a href="#listener" class="headerlink" title="$listener"></a>$listener</h4><p>包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on=”$listeners” 传入内部组件——在创建更高层次的组件时非常有用。（孙传父专用）</p>
<p>在父组件当中，最外层组件</p>
<pre class=" language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>template</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Child1</span>
      <span class="token attr-name">:child1Info</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>child1<span class="token punctuation">"</span></span>
      <span class="token attr-name">:child2Info</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>child2<span class="token punctuation">"</span></span>
      <span class="token attr-name"><span class="token namespace">v-on:</span>test1</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>onTest1<span class="token punctuation">"</span></span>
      <span class="token attr-name"><span class="token namespace">v-on:</span>test2</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>onTest2<span class="token punctuation">"</span></span>
    <span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>Child1</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>template</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">></span></span><span class="token script language-javascript">
  <span class="token keyword">import</span> Child1 <span class="token keyword">from</span> <span class="token string">"./child1"</span><span class="token punctuation">;</span>
  <span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    <span class="token function">data</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
      <span class="token keyword">return</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
        child1<span class="token punctuation">:</span> <span class="token string">"hahha"</span><span class="token punctuation">,</span>
        child2<span class="token punctuation">:</span> <span class="token string">"asdsdasd"</span><span class="token punctuation">,</span>
      <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">;</span>
    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">,</span>
    components<span class="token punctuation">:</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span> Child1 <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">,</span>
    methods<span class="token punctuation">:</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
      <span class="token function">onTest1</span><span class="token punctuation">(</span>msg<span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"test1 running..."</span><span class="token punctuation">,</span> msg<span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">,</span>
      <span class="token function">onTest2</span><span class="token punctuation">(</span>msg<span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"test2 running"</span><span class="token punctuation">,</span> msg<span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">,</span>
    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">,</span>
  <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">;</span>
</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">></span></span>
··· //在子组件中 ```html
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>template</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>child-1<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">></span></span>在子组件当中:<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">></span></span>props-child1Info: <span class="token entity" title="&#123;">&amp;#123;</span><span class="token entity" title="&#123;">&amp;#123;</span>child1Info<span class="token entity" title="&#125;">&amp;#125;</span><span class="token entity" title="&#125;">&amp;#125;</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">></span></span>$attrs: <span class="token entity" title="&#123;">&amp;#123;</span><span class="token entity" title="&#123;">&amp;#123;</span>$attrs<span class="token entity" title="&#125;">&amp;#125;</span><span class="token entity" title="&#125;">&amp;#125;</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>hr</span> <span class="token punctuation">/></span></span>
    <span class="token comment" spellcheck="true">&lt;!-- Child2组件中能直接触发test的原因在于 B组件调用C组件时 使用 v-on 绑定了$listeners 属性 --></span>
    <span class="token comment" spellcheck="true">&lt;!-- 通过v-bind 绑定$attrs属性，Child2组件可以直接获取到A组件中传递下来的props（除了child1组件中props声明的） --></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Child2</span> <span class="token attr-name">v-bind</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>$attrs<span class="token punctuation">"</span></span> <span class="token attr-name">v-on</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>$listeners<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>Child2</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>template</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">></span></span><span class="token script language-javascript">
  <span class="token keyword">import</span> Child2 <span class="token keyword">from</span> <span class="token string">"./child2"</span><span class="token punctuation">;</span>
  <span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    props<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token string">"child1Info"</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token function">data</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
      <span class="token keyword">return</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span><span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">;</span>
    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">,</span>
    components<span class="token punctuation">:</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span> Child2 <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">,</span>
    <span class="token function">mounted</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
      <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">$emit</span><span class="token punctuation">(</span><span class="token string">"test1"</span><span class="token punctuation">,</span> <span class="token string">"嘻嘻"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">,</span>
  <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">;</span>
</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">></span></span></code></pre>
<p>//在孙子组件当中：</p>
<pre class=" language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>template</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>child-2<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">></span></span>在最里层组件当中child2:<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">></span></span>props-child2Info: <span class="token entity" title="&#123;">&amp;#123;</span><span class="token entity" title="&#123;">&amp;#123;</span>child2Info<span class="token entity" title="&#125;">&amp;#125;</span><span class="token entity" title="&#125;">&amp;#125;</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">></span></span>$attrs 的值: <span class="token entity" title="&#123;">&amp;#123;</span><span class="token entity" title="&#123;">&amp;#123;</span>$attrs<span class="token entity" title="&#125;">&amp;#125;</span><span class="token entity" title="&#125;">&amp;#125;</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>hr</span> <span class="token punctuation">/></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>template</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">></span></span><span class="token script language-javascript">
  <span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    props<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token string">"child2Info"</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token function">data</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
      <span class="token keyword">return</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span><span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">;</span>
    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">,</span>
    <span class="token function">mounted</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
      <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">$emit</span><span class="token punctuation">(</span><span class="token string">"test2"</span><span class="token punctuation">,</span> <span class="token string">"哈哈"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">,</span>
  <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">;</span>
</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">></span></span></code></pre>
<h4 id="代码详细说明："><a href="#代码详细说明：" class="headerlink" title="代码详细说明："></a>代码详细说明：</h4><p><img src="https://yangyunhaiimagesoss.oss-cn-shanghai.aliyuncs.com/2009171558_1600329518020.png"></p>
<p><img src="https://yangyunhaiimagesoss.oss-cn-shanghai.aliyuncs.com/2009171558_1600329528854.png"></p>
<p><img src="https://yangyunhaiimagesoss.oss-cn-shanghai.aliyuncs.com/2009171600_1600329603285.png"></p>
<h4 id="9-Vue中双向数据绑定是如何实现的"><a href="#9-Vue中双向数据绑定是如何实现的" class="headerlink" title="9.Vue中双向数据绑定是如何实现的?"></a>9.<code>Vue</code>中双向数据绑定是如何实现的?</h4><p>1.<code>vue.js</code> 则是采用数据劫持结合发布者-订阅者模式的方式。</p>
<p>2.通过<code>Object.defineProperty()</code>来劫持各个属性的<code>setter</code>，<code>getter</code>.</p>
<p>3.在数据变动时发布消息给订阅者，触发相应的监听回调。我们先来看<code>Object.defineProperty()</code>这个方法：</p>
<pre class=" language-javascript"><code class="language-javascript"><span class="token keyword">var</span> obj <span class="token operator">=</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span><span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">;</span>
Object<span class="token punctuation">.</span><span class="token function">defineProperty</span><span class="token punctuation">(</span>obj<span class="token punctuation">,</span> <span class="token string">"name"</span><span class="token punctuation">,</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
  <span class="token keyword">get</span><span class="token punctuation">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"我被获取了"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> val<span class="token punctuation">;</span>
  <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">,</span>
  <span class="token keyword">set</span><span class="token punctuation">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span>newVal<span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"我被设置了"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">,</span>
<span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
obj<span class="token punctuation">.</span>name <span class="token operator">=</span> <span class="token string">"fei"</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">//在给obj设置name属性的时候，触发了set这个方法</span>
<span class="token keyword">var</span> val <span class="token operator">=</span> obj<span class="token punctuation">.</span>name<span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">//在得到obj的name属性，会触发get方法</span></code></pre>
<h4 id="10-单页面应用和多页面应用区别及优缺点"><a href="#10-单页面应用和多页面应用区别及优缺点" class="headerlink" title="10.单页面应用和多页面应用区别及优缺点?"></a>10.单页面应用和多页面应用区别及优缺点?</h4><p>单页面应用（<code>SPA</code>），通俗一点说就是指只有一个主页面的应用，浏览器一开始要加载所有必须的 <code>html</code>, <code>js</code>, <code>css</code>。所有的页面内容都包含在这个所谓的主页面中。但在写的时候，还是会分开写（页面片段），然后在交互的时候由路由程序动态载入，单页面的页面跳转，仅刷新局部资源。多应用于<code>pc</code>端。</p>
<p>多页面（<code>MPA</code>），就是指一个应用中有多个页面，页面跳转时是整页刷新</p>
<h4 id="单页面的优点："><a href="#单页面的优点：" class="headerlink" title="单页面的优点："></a>单页面的优点：</h4><p>1，用户体验好，快，内容的改变不需要重新加载整个页面，基于这一点 spa 对服务器压力较小</p>
<p>2，前后端分离</p>
<p>3，页面效果会比较炫酷（比如切换页面内容时的专场动画）</p>
<h4 id="单页面缺点："><a href="#单页面缺点：" class="headerlink" title="单页面缺点："></a>单页面缺点：</h4><p>1，不利于<code>seo</code></p>
<p>2，导航不可用，如果一定要导航需要自行实现前进、后退。（由于是单页面不能用浏览器的前进后退功能，所以需要自己建立堆栈管理）</p>
<p>3，初次加载时耗时多</p>
<p>4，页面复杂度提高很多</p>
<h4 id="11-vue中v-if和v-for优先级"><a href="#11-vue中v-if和v-for优先级" class="headerlink" title="11.vue中v-if和v-for优先级?"></a>11.<code>vue</code>中<code>v-if</code>和<code>v-for</code>优先级?</h4><p><code>v-for</code>和<code>v-if</code>不应该一起使用，必要情况下应该替换成<code>computed</code>属性。原因：<code>v-for</code>比<code>v-if</code>优先，如果每一次都需要遍历整个数组，将会影响速度，尤其是当之需要渲染很小一部分的时候。</p>
<pre class=" language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>li</span> <span class="token attr-name">v-for</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>user in users<span class="token punctuation">"</span></span> <span class="token attr-name">v-if</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>user.isActive<span class="token punctuation">"</span></span> <span class="token attr-name">:key</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>user.id<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
  <span class="token entity" title="&#123;">&amp;#123;</span><span class="token entity" title="&#123;">&amp;#123;</span> user.name <span class="token entity" title="&#125;">&amp;#125;</span><span class="token entity" title="&#125;">&amp;#125;</span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>li</span><span class="token punctuation">></span></span></code></pre>
<p>如上情况，即使 100 个 user 中之需要使用一个数据，也会循环整个数组。</p>
<pre class=" language-javascript"><code class="language-javascript">omputed<span class="token punctuation">:</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
  activeUsers<span class="token punctuation">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span>users<span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span>user<span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
      <span class="token keyword">return</span> user<span class="token punctuation">.</span>isActive
    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">)</span>
  <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
<span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span></code></pre>
<pre class=" language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>ul</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>li</span> <span class="token attr-name">v-for</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>user in activeUsers<span class="token punctuation">"</span></span> <span class="token attr-name">:key</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>user.id<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token entity" title="&#123;">&amp;#123;</span><span class="token entity" title="&#123;">&amp;#123;</span> user.name <span class="token entity" title="&#125;">&amp;#125;</span><span class="token entity" title="&#125;">&amp;#125;</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>li</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>ul</span><span class="token punctuation">></span></span></code></pre>
<h4 id="12-Vue事件的修饰符（）？"><a href="#12-Vue事件的修饰符（）？" class="headerlink" title="12.Vue事件的修饰符（）？"></a>12.<code>Vue</code>事件的修饰符（）？</h4><p>1)<code>.stop`：等同于`JavaScript`中的`event.stopPropagation()</code>，防止事件冒泡</p>
<p>2)<code>.prevent</code>：等同于<code>JavaScript</code>中的<code>event.preventDefault()</code>，防止执行预设的行为（如果事件可取消，则取消该事件，而不停止事件的进一步传播）</p>
<p>3)<code>.capture</code>：与事件冒泡的方向相反，事件捕获由外到内</p>
<p>4)<code>.self</code>：只会触发自己范围内的事件，不包含子元素</p>
<p>5)<code>.once</code>：只会触发一次</p>
<p>6)<code>.passive</code>：<code>passive</code>表示<code>listener</code>函数不会调用<code>preventDefault（）</code></p>
<p><code>passive</code>主要用在移动端的<code>scroll</code>事件，来提高浏览器响应速度，提升用户体验。因为<code>passive=true</code>等于提前告诉了浏览器，<code>touchstart</code>和<code>touchmove</code>不会阻止默认事件，手刚开始触摸，浏览器就可以立刻给与响应；</p>
<p>否则，手触摸屏幕了，但要等待<code>touchstart</code>和<code>touchmove</code>的结果，多了这一步，响应时间就长了，用户体验也就差了。</p>
<h4 id="13-Vue的两个核心是什么？"><a href="#13-Vue的两个核心是什么？" class="headerlink" title="13.Vue的两个核心是什么？"></a>13.<code>Vue</code>的两个核心是什么？</h4><h4 id="1、数据驱动："><a href="#1、数据驱动：" class="headerlink" title="1、数据驱动："></a>1、数据驱动：</h4><p>在 vue 中，数据的改变会驱动视图的自动更新。传统的做法是需要手动改变 DOM 来使得视图更新，而 vue 只需要改变数据。</p>
<h4 id="2、组件"><a href="#2、组件" class="headerlink" title="2、组件"></a>2、组件</h4><p>组件化开发，优点很多，可以很好的降低数据之间的耦合度。将常用的代码封装成组件之后（vue 组件封装方法），就能高度的复用，提高代码的可重用性。一个页面/模块可以由多个组件所组成。</p>
<h5 id="14、react和vue的区别"><a href="#14、react和vue的区别" class="headerlink" title="14、react和vue的区别"></a>14、<code>react</code>和<code>vue</code>的区别</h5><h4 id="相同点"><a href="#相同点" class="headerlink" title="相同点"></a>相同点</h4><ul>
<li>数据驱动页面提供响应式的试图组件</li>
<li>都有<code>virtual DOM</code>,组件化的开发通过<code>props</code>参数进行父子之间组件传递数据都实现了<code>webComponents</code>规范</li>
<li>数据流动单向都支持服务器的渲染 SSR</li>
<li>都有支持<code>native</code>的方法<code>react</code>有<code>React native vue</code>有<code>wexx</code></li>
</ul>
<h4 id="不同点"><a href="#不同点" class="headerlink" title="不同点"></a>不同点</h4><ul>
<li>数据绑定<code>Vue</code>实现了双向的数据绑定<code>react</code>数据流动是单向的</li>
<li>数据渲染大规模的数据渲染<code>react</code>更快</li>
<li>使用场景<code>React</code>配合<code>Redux</code>架构适合大规模多人协作复杂项目 Vue 适合小快的项目</li>
<li>开发风格<code>react</code>推荐做法<code>jsx</code> + <code>inline style</code>把<code>html</code>和<code>css</code>都写在<code>js</code>了</li>
<li><code>vue</code>是采用<code>webpack</code> +<code>vue-loader</code>单文件组件格式<code>html</code>, <code>js</code>, <code>css</code>同一个文件</li>
</ul>
<h4 id="15-vue3-0有哪些新特性"><a href="#15-vue3-0有哪些新特性" class="headerlink" title="15.vue3.0有哪些新特性"></a>15.<code>vue3.0</code>有哪些新特性</h4><h4 id="vue3-0-的设计目标"><a href="#vue3-0-的设计目标" class="headerlink" title="vue3.0 的设计目标"></a>vue3.0 的设计目标</h4><ul>
<li>更小</li>
<li>更快</li>
<li>加强 TypeScript 支持</li>
<li>加强 API 设计一致性</li>
<li>提高自身可维护性</li>
<li>开放更多底层功能</li>
</ul>
<p>具体可以从以下方面来理解</p>
<h4 id="1，压缩包体积更小"><a href="#1，压缩包体积更小" class="headerlink" title="1，压缩包体积更小"></a>1，压缩包体积更小</h4><p>当前最小化并被压缩的 <code>Vue</code> 运行时大小约为 20kB（2.6.10 版为 22.8kB）。<code>Vue 3.0</code>捆绑包的大小大约会<code>减少一半</code>，即只有<code>10kB</code>！</p>
<h4 id="2，Object-defineProperty-gt-Proxy"><a href="#2，Object-defineProperty-gt-Proxy" class="headerlink" title="2，Object.defineProperty -&gt; Proxy"></a>2，Object.defineProperty -&gt; Proxy</h4><p><code>Object.defineProperty</code>是一个相对比较昂贵的操作，因为它直接操作对象的属性，颗粒度比较小。将它替换为<code>es6</code>的<code>Proxy</code>，在目标对象之上架了一层拦截，代理的是对象而不是对象的属性。这样可以将原本对对象属性的操作变为对整个对象的操作，颗粒度变大。</p>
<p><code>javascript</code>引擎在解析的时候希望对象的结构越稳定越好，如果对象一直在变，可优化性降低，<code>proxy</code>不需要对原始对象做太多操作。</p>
<h4 id="3，Virtual-DOM-重构"><a href="#3，Virtual-DOM-重构" class="headerlink" title="3，Virtual DOM 重构"></a>3，Virtual DOM 重构</h4><p>vdom 的本质是一个抽象层，用<code>javascript</code>描述界面渲染成什么样子。<code>react</code>用<code>jsx</code>，没办法检测出可以优化的动态代码，所以做时间分片，<code>vue</code>中足够快的话可以不用时间分片。</p>
<h4 id="传统-vdom-的性能瓶颈："><a href="#传统-vdom-的性能瓶颈：" class="headerlink" title="传统 vdom 的性能瓶颈："></a>传统 vdom 的性能瓶颈：</h4><p>虽然 Vue 能够保证触发更新的组件最小化，但在单个组件内部依然需要遍历该组件的整个 vdom 树。<br>传统 vdom 的性能跟模版大小正相关，跟动态节点的数量无关。在一些组件整个模版内只有少量动态节点的情况下，这些遍历都是性能的浪费。<br><code>JSX</code> 和手写的 <code>render function</code> 是完全动态的，过度的灵活性导致运行时可以用于优化的信息不足<br>那为什么不直接抛弃 vdom 呢？</p>
<p>高级场景下手写 <code>render function</code> 获得更强的表达力</p>
<p>生成的代码更简洁</p>
<h4 id="兼容-2-x"><a href="#兼容-2-x" class="headerlink" title="兼容 2.x"></a>兼容 2.x</h4><p><code>vue</code>的特点是底层为<code>Virtual DOM</code>，上层包含有大量静态信息的模版。为了兼容手写 <code>render function</code>，最大化利用模版静态信息，<code>vue3.0</code>采用了动静结合的解决方案，将<code>vdom</code>的操作颗粒度变小，每次触发更新不再以组件为单位进行遍历，主要更改如下</p>
<p>将模版基于动态节点指令切割为嵌套的区块</p>
<p>每个区块内部的节点结构是固定的</p>
<p>每个区块只需要以一个 Array 追踪自身包含的动态节点</p>
<p>vue3.0 将 vdom 更新性能由与模版整体大小相关提升为与动态内容的数量相关</p>
<h4 id="4-更多编译时优化"><a href="#4-更多编译时优化" class="headerlink" title="4, 更多编译时优化"></a>4, 更多编译时优化</h4><p>Slot 默认编译为函数：父子之间不存在强耦合，提升性能<br>Monomorphic vnode factory：参数一致化，给它 children 信息，<br>Compiler-generated flags for vnode/children types</p>
<h4 id="5，选用-Function-based-API"><a href="#5，选用-Function-based-API" class="headerlink" title="5，选用 Function_based API"></a>5，选用 Function_based API</h4><p>为什么撤销 <code>Class API</code> ?</p>
<p>1，更好地支持<code>TypeScript</code></p>
<p><code>Props</code> 和其它需要注入到 <code>this</code> 的属性导致类型声明依然存在问题<br><code>Decorators</code>提案的严重不稳定使得依赖它的方案具有重大风险<br>2，除了类型支持以外 <code>Class API</code> 并不带来任何新的优势</p>
<p>3，<code>vue</code>中的<code>UI</code>组件很少用到继承，一般都是组合，可以用<code>Function-based API</code></p>
<h4 id="16-Vue性能优化方法"><a href="#16-Vue性能优化方法" class="headerlink" title="16.Vue性能优化方法"></a>16.<code>Vue</code>性能优化方法</h4><h3 id="1）编码阶段"><a href="#1）编码阶段" class="headerlink" title="1）编码阶段"></a>1）编码阶段</h3><ul>
<li>尽量减少 data 中的数据，data 中的数据都会增加 getter 和 setter，会收集对应的 watcher；</li>
<li>如果需要使用 v-for 给每项元素绑定事件时使用事件代理；</li>
<li>SPA 页面采用 keep-alive 缓存组件；</li>
<li>在更多的情况下，使用 v-if 替代 v-show；</li>
<li>key 保证唯一；</li>
<li>使用路由懒加载、异步组件；</li>
<li>防抖、节流；</li>
<li>第三方模块按需导入；</li>
<li>长列表滚动到可视区域动态加载；</li>
<li>图片懒加载；</li>
</ul>
<h3 id="2）用户体验："><a href="#2）用户体验：" class="headerlink" title="2）用户体验："></a>2）用户体验：</h3><ul>
<li>骨架屏；</li>
<li>PWA；</li>
<li>还可以使用缓存(客户端缓存、服务端缓存)优化、服务端开启 gzip 压缩等。</li>
</ul>
<h3 id="3）SEO-优化"><a href="#3）SEO-优化" class="headerlink" title="3）SEO 优化"></a>3）SEO 优化</h3><ul>
<li>预渲染；</li>
<li>服务端渲染 SSR；</li>
</ul>
<h3 id="4）打包优化"><a href="#4）打包优化" class="headerlink" title="4）打包优化"></a>4）打包优化</h3><ul>
<li>压缩代码；</li>
<li>Tree Shaking/Scope Hoisting；</li>
<li>使用 cdn 加载第三方模块；</li>
<li>多线程打包 happypack；</li>
<li>splitChunks 抽离公共文件；</li>
<li>sourceMap 优化；</li>
</ul>
<h4 id="17-v-model的原理"><a href="#17-v-model的原理" class="headerlink" title="17.v-model的原理"></a>17.<code>v-model</code>的原理</h4><p><code>v-model</code>本质就是一个语法糖，可以看成是 value + input 方法的语法糖。可以通过 model 属性的 prop 和 event 属性来进行自定义。</p>
<blockquote>
<p>原生的 v-model，会根据标签的不同生成不同的事件和属性。</p>
</blockquote>
<blockquote>
<p>v-model 在内部为不同的输入元素使用不同的属性并抛出不同的事件：</p>
</blockquote>
<p>1）text 和 textarea 元素使用 value 属性和 input 事件；</p>
<p>2）checkbox 和 radio 使用 checked 属性和 change 事件；</p>
<p>3）select 字段将 value 作为 prop 并将 change 作为事件。</p>
<h3 id="例子"><a href="#例子" class="headerlink" title="例子"></a>例子</h3><pre class=" language-javaScript"><code class="language-javaScript">model: &#123;
  prop: 'checked',
  event: 'change'
&#125;</code></pre>
<p>如果想要更改 <code>checked</code> 这个 <code>prop</code> 可以在 <code>Vue</code> 的 <code>instance</code> 中用以下这行代码发送 <code>change</code> 这个 <code>event</code>，并将目标的变动值传给 <code>checked</code> 这个 <code>prop</code>。</p>
<pre class=" language-javaScript"><code class="language-javaScript">this.$emit("change", $event.target.value);</code></pre>
<h4 id="18-nextTick的实现原理是什么"><a href="#18-nextTick的实现原理是什么" class="headerlink" title="18.nextTick的实现原理是什么?"></a>18.<code>nextTick</code>的实现原理是什么?</h4><p>在下次 <code>DOM</code> 更新循环结束之后执行延迟回调。<code>nextTick</code>主要使用了宏任务和微任务。根据执行环境分别尝试采用</p>
<ul>
<li>Promise</li>
<li>MutationObserver</li>
<li>setImmediate</li>
<li>如果以上都不行则采用 setTimeout</li>
</ul>
<p>定义了一个异步方法，多次调用<code>nextTick</code>会将方法存入队列中，通过这个异步方法清空当前队列。</p>
<h4 id="19-谈谈Computed和Watch"><a href="#19-谈谈Computed和Watch" class="headerlink" title="19.谈谈Computed和Watch!"></a>19.谈谈<code>Computed</code>和<code>Watch</code>!</h4><p><code>Computed</code>本质是一个具备缓存的<code>watcher</code>，依赖的属性发生变化就会更新视图。</p>
<p>适用于计算比较消耗性能的计算场景。当表达式过于复杂时，在模板中放入过多逻辑会让模板难以维护，可以将复杂的逻辑放入计算属性中处理。</p>
<p><code>Watch</code>没有缓存性，更多的是观察的作用，可以监听某些数据执行回调。</p>
<p>当我们需要深度监听对象中的属性时，可以打开<code>deep：true</code>选项，这样便会对对象中的每一项进行监听。</p>
<p>这样会带来性能问题，优化的话可以使用字符串形式监听，如果没有写到组件中，不要忘记使用<code>unWatch</code>手动注销哦。</p>
<h4 id="20-说一下Vue的生命周期"><a href="#20-说一下Vue的生命周期" class="headerlink" title="20.说一下Vue的生命周期"></a>20.说一下<code>Vue</code>的生命周期</h4><p><code>beforeCreate</code>是<code>new Vue()</code>之后触发的第一个钩子，在当前阶段<code>data</code>、<code>methods</code>、<code>computed</code>以及<code>watch</code>上的数据和方法都不能被访问。</p>
<p><code>created</code>在实例创建完成后发生，当前阶段已经完成了数据观测，也就是可以使用数据，更改数据，在这里更改数据不会触发 updated 函数。可以做一些初始数据的获取，在当前阶段无法与 Dom 进行交互，如果非要想，可以通过<code>vm.$nextTick</code>来访问<code>Dom</code>。</p>
<p><code>beforeMount</code>发生在挂载之前，在这之前<code>template</code>模板已导入渲染函数编译。而当前阶段虚拟<code>Dom</code>已经创建完成，即将开始渲染。在此时也可以对数据进行更改，不会触发<code>updated</code>。<br><code>mounted</code>在挂载完成后发生，在当前阶段，真实的<code>Dom</code>挂载完毕，数据完成双向绑定，可以访问到<code>Dom</code>节点，使用<code>$refs</code>属性对<code>Dom</code>进行操作。</p>
<p><code>beforeUpdate</code>发生在更新之前，也就是响应式数据发生更新，虚拟<code>dom</code>重新渲染之前被触发，你可以在当前阶段进行更改数据，不会造成重渲染。</p>
<p><code>updated</code>发生在更新完成之后，当前阶段组件<code>Dom</code>已完成更新。要注意的是避免在此期间更改数据，因为这可能会导致无限循环的更新。<br><code>beforeDestroy</code>发生在实例销毁之前，在当前阶段实例完全可以被使用，我们可以在这时进行善后收尾工作，比如清除计时器。</p>
<p><code>destroyed</code>发生在实例销毁之后，这个时候只剩下了<code>dom</code>空壳。组件已被拆解，数据绑定被卸除，监听被移出，子实例也统统被销毁。</p>
<h3 id="21-Vue模版编译原理知道吗，能简单说一下"><a href="#21-Vue模版编译原理知道吗，能简单说一下" class="headerlink" title="21.Vue模版编译原理知道吗，能简单说一下?"></a>21.<code>Vue</code>模版编译原理知道吗，能简单说一下?</h3><p>简单说，<code>Vue</code>的编译过程就是将<code>template</code>转化为<code>render</code>函数的过程。会经历以下阶段：</p>
<ul>
<li>生成 AST 树</li>
<li>优化</li>
<li>codegen</li>
</ul>
<p>首先解析模版，生成<code>AST</code>语法树(一种用<code>JavaScript</code>对象的形式来描述整个模板)。<br>使用大量的正则表达式对模板进行解析，遇到标签、文本的时候都会执行对应的钩子进行相关处理。</p>
<p><code>Vue</code>的数据是响应式的，但其实模板中并不是所有的数据都是响应式的。有一些数据首次渲染后就不会再变化，对应的<code>DOM</code>也不会变化。那么优化过程就是深度遍历 AST 树，按照相关条件对树节点进行标记。这些被标记的节点(静态节点)我们就可以跳过对它们的比对，对运行时的模板起到很大的优化作用。</p>
<p>编译的最后一步是将优化后的<code>AST</code>树转换为可执行的代码。</p>
<h3 id="22-Vue的优点及缺点"><a href="#22-Vue的优点及缺点" class="headerlink" title="22.Vue的优点及缺点?"></a>22.<code>Vue</code>的优点及缺点?</h3><p>首先 Vue 最核心的两个特点，响应式和组件化。</p>
<h3 id="响应式："><a href="#响应式：" class="headerlink" title="响应式："></a>响应式：</h3><p>这也就是 vue.js 最大的优点，通过 MVVM 思想实现数据的双向绑定，通过虚拟 DOM 让我们可以用数据来操作 DOM，而不必去操作真实的 DOM，提升了性能。且让开发者有更多的时间去思考业务逻辑。</p>
<h3 id="组件化：-1"><a href="#组件化：-1" class="headerlink" title="组件化："></a>组件化：</h3><p>把一个单页应用中的各个模块拆分到一个个组件当中，或者把一些公共的部分抽离出来做成一个可复用的组件。所以组件化带来的好处就是，提高了开发效率，方便重复使用，使项目的可维护性更强。</p>
<h3 id="虚拟-DOM：-1"><a href="#虚拟-DOM：-1" class="headerlink" title="虚拟 DOM："></a>虚拟 DOM：</h3><p>当然，这个不是 vue 中独有的。</p>
<h3 id="缺点："><a href="#缺点：" class="headerlink" title="缺点："></a>缺点：</h3><p>基于对象配置文件的写法，也就是 options 写法，开发时不利于对一个属性的查找。另外一些缺点，在小项目中感觉不太出什么，vuex 的魔法字符串，对 ts 的支持。兼容性上存在一些问题。</p>
<h3 id="不利于-seo"><a href="#不利于-seo" class="headerlink" title="不利于 seo:"></a>不利于 seo:</h3><p>导航不可用，如果一定要导航需要自行实现前进、后退。（由于是单页面不能用浏览器的前进后退功能，所以需要自己建立堆栈管理）。<br>初次加载时耗时多。</p>
<h3 id="23-Vue中hash模式和history模式的区别"><a href="#23-Vue中hash模式和history模式的区别" class="headerlink" title="23.Vue中hash模式和history模式的区别?"></a>23.<code>Vue</code>中<code>hash</code>模式和<code>history</code>模式的区别?</h3><p>最明显的是在显示上，<code>hash</code>模式的<code>URL</code>中会夹杂着<code>#</code>号，而 history 没有。</p>
<p><code>Vue</code>底层对它们的实现方式不同。hash 模式是依靠<code>onhashchange</code>事件(监听<code>location.hash</code>的改变)，而<code>history</code>模式是主要是依靠的<code>HTML5 history</code>中新增的两个方法，<code>pushState()</code>可以改变 url 地址且不会发送请求，<code>replaceState()</code>可以读取历史记录栈,还可以对浏览器记录进行修改。</p>
<p>当真正需要通过<code>URL</code>向后端发送 HTTP 请求的时候，比如常见的用户手动输入<code>URL</code>后回车，或者是刷新(重启)浏览器，这时候<code>history</code>模式需要后端的支持。</p>
<p>因为<code>history</code>模式下，前端的<code>URL</code>必须和实际向后端发送请求的 URL 一致，例如有一个<code>URL</code>是带有路径<code>path</code>的(例如<code>www.lindaidai.wang/blogs/id</code>)，如果后端没有对这个路径做处理的话，就会返回<code>404</code>错误。所以需要后端增加一个覆盖所有情况的候选资源，一般会配合前端给出的一个<code>404</code>页面。</p>
<p>hash:</p>
<pre class=" language-javaScript"><code class="language-javaScript">window.onhashchange = function (event) &#123;
  // location.hash获取到的是包括#号的，如"#heading-3"
  // 所以可以截取一下
  let hash = location.hash.slice(1);
&#125;;</code></pre>
<h4 id="24-你的接口请求一般放在哪个生命周期中？"><a href="#24-你的接口请求一般放在哪个生命周期中？" class="headerlink" title="24.你的接口请求一般放在哪个生命周期中？"></a>24.你的接口请求一般放在哪个生命周期中？</h4><p>接口请求一般放在<code>mounted</code>中，但需要注意的是服务端渲染时不支持<code>mounted</code>，需要放到<code>created</code>中。</p>
<h4 id="25-Vue-SSR渲染原理？"><a href="#25-Vue-SSR渲染原理？" class="headerlink" title="25.Vue SSR渲染原理？"></a>25.<code>Vue SSR</code>渲染原理？</h4><h3 id="优点："><a href="#优点：" class="headerlink" title="优点："></a>优点：</h3><h4 id="更利于-SEO"><a href="#更利于-SEO" class="headerlink" title="更利于 SEO"></a>更利于 SEO</h4><p>不同爬虫工作原理类似，只会爬取源码，不会执行网站的任何脚本（Google 除外，据说 Googlebot 可以运行 javaScript）。使用了 Vue 或者其它 MVVM 框架之后，页面大多数 DOM 元素都是在客户端根据 js 动态生成，可供爬虫抓取分析的内容大大减少。另外，浏览器爬虫不会等待我们的数据完成之后再去抓取我们的页面数据。服务端渲染返回给客户端的是已经获取了异步数据并执行 JavaScript 脚本的最终 HTML，网络爬中就可以抓取到完整页面的信息。</p>
<h4 id="更利于首屏渲染"><a href="#更利于首屏渲染" class="headerlink" title="更利于首屏渲染"></a>更利于首屏渲染</h4><p>首屏的渲染是 node 发送过来的 html 字符串，并不依赖于 js 文件了，这就会使用户更快的看到页面的内容。尤其是针对大型单页应用，打包后文件体积比较大，普通客户端渲染加载所有所需文件时间较长，首页就会有一个很长的白屏等待时间。</p>
<h3 id="场景："><a href="#场景：" class="headerlink" title="场景："></a>场景：</h3><p>交互少，数据多，例如新闻，博客，论坛类等</p>
<h3 id="原理："><a href="#原理：" class="headerlink" title="原理："></a>原理：</h3><p>相当于服务端前面加了一层 url 分配，可以假想为服务端的中间层，</p>
<p>当地址栏 url 改变或者直接刷新，其实直接从服务器返回内容，是一个包含内容部分的 html 模板，是服务端渲染</p>
<p>而在交互过程中则是 ajax 处理操作，局部刷新，首先是在 history 模式下，通过 history. pushState 方式进而 url 改变，然后请求后台数据服务，拿到真正的数据，做到局部刷新，这时候接收的是数据而不是模板</p>
<h3 id="缺点"><a href="#缺点" class="headerlink" title="缺点"></a>缺点</h3><h4 id="服务端压力较大"><a href="#服务端压力较大" class="headerlink" title="服务端压力较大"></a>服务端压力较大</h4><p>本来是通过客户端完成渲染，现在统一到服务端 node 服务去做。尤其是高并发访问的情况，会大量占用服务端 CPU 资源；</p>
<h4 id="开发条件受限"><a href="#开发条件受限" class="headerlink" title="开发条件受限"></a>开发条件受限</h4><p>在服务端渲染中，created 和 beforeCreate 之外的生命周期钩子不可用，因此项目引用的第三方的库也不可用其它生命周期钩子，这对引用库的选择产生了很大的限制；</p>
<h4 id="安全问题"><a href="#安全问题" class="headerlink" title="安全问题"></a>安全问题</h4><p>因为做了 node 服务，因此安全方面也需要考虑 DDOS 攻击和 sql 注入</p>
<h4 id="学习成本相对较高"><a href="#学习成本相对较高" class="headerlink" title="学习成本相对较高"></a>学习成本相对较高</h4><p>除了对 webpack、Vue 要熟悉，还需要掌握 node、Express 相关技术。相对于客户端渲染，项目构建、部署过程更加复杂。</p>
<h4 id="26-new-Vue-发生了什么？"><a href="#26-new-Vue-发生了什么？" class="headerlink" title="26.new Vue() 发生了什么？"></a>26.<code>new Vue()</code> 发生了什么？</h4><p>1）<code>new Vue()</code>是创建<code>Vue</code>实例，它内部执行了根实例的初始化过程。</p>
<p>2）具体包括以下操作：</p>
<ul>
<li>选项合并</li>
<li><code>$children</code>，<code>$refs</code>，<code>$slots</code>，<code>$createElement</code>等实例属性的方法初始化</li>
<li>自定义事件处理</li>
<li>数据响应式处理</li>
<li>生命周期钩子调用 （<code>beforecreate created</code>）</li>
<li>可能的挂载</li>
</ul>
<h3 id="总结：-2"><a href="#总结：-2" class="headerlink" title="总结："></a>总结：</h3><p><code>new Vue()</code>创建了根实例并准备好数据和方法，未来执行挂载时，此过程还会递归的应用于它的子组件上，最终形成一个有紧密关系的组件实例树。</p>
<h4 id="27-Vue-use是干什么的？原理是什么？"><a href="#27-Vue-use是干什么的？原理是什么？" class="headerlink" title="27.Vue.use是干什么的？原理是什么？"></a>27.<code>Vue.use</code>是干什么的？原理是什么？</h4><blockquote>
<p><code>vue.use</code> 是用来使用插件的，我们可以在插件中扩展全局组件、指令、原型方法等。</p>
</blockquote>
<p>1､检查插件是否注册，若已注册，则直接跳出；</p>
<p>2､处理入参，将第一个参数之后的参数归集，并在首部塞入 <code>this</code> 上下文；</p>
<p>3､执行注册方法，调用定义好的 <code>install</code> 方法，传入处理的参数，若没有 <code>install</code> 方法并且插件本身为 <code>function</code> 则直接进行注册；</p>
<ol>
<li>插件不能重复的加载</li>
</ol>
<p><code>install</code> 方法的第一个参数是 vue 的构造函数，其他参数是 Vue.set 中除了第一个参数的其他参数； 代码：<code>args.unshift(this)</code></p>
<ol start="2">
<li>调用插件的 install 方法 代码：</li>
</ol>
<pre><code>typeof plugin.install === &#39;function&#39;</code></pre>
<ol start="3">
<li>插件本身是一个函数，直接让函数执行。 代码：</li>
</ol>
<pre><code>plugin.apply(null, args)</code></pre>
<ol start="4">
<li>缓存插件。 代码：</li>
</ol>
<pre><code>installedPlugins.push(plugin)</code></pre>
<h4 id="28-请说一下响应式数据的理解？"><a href="#28-请说一下响应式数据的理解？" class="headerlink" title="28.请说一下响应式数据的理解？"></a>28.请说一下响应式数据的理解？</h4><ol>
<li><p>对象内部通过<code>defineReactive</code>方法，使用 <code>Object.defineProperty()</code> 监听数据属性的 <code>get</code> 来进行数据依赖收集，再通过 <code>set</code> 来完成数据更新的派发；</p>
</li>
<li><p>数组则通过重写数组方法来实现的。扩展它的 7 个变更⽅法，通过监听这些方法可以做到依赖收集和派发更新；</p>
</li>
</ol>
<h4 id="对应源码"><a href="#对应源码" class="headerlink" title="对应源码"></a>对应源码</h4><pre class=" language-javascript"><code class="language-javascript">Object<span class="token punctuation">.</span><span class="token function">defineProperty</span><span class="token punctuation">(</span>obj<span class="token punctuation">,</span> key<span class="token punctuation">,</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
  enumerable<span class="token punctuation">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
  configurable<span class="token punctuation">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
  <span class="token keyword">get</span><span class="token punctuation">:</span> <span class="token keyword">function</span> <span class="token function">reactiveGetter</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    <span class="token keyword">const</span> value <span class="token operator">=</span> getter <span class="token operator">?</span> getter<span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span>obj<span class="token punctuation">)</span> <span class="token punctuation">:</span> val<span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>Dep<span class="token punctuation">.</span>target<span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
      dep<span class="token punctuation">.</span><span class="token function">depend</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">// ** 收集依赖 ** /</span>
      <span class="token keyword">if</span> <span class="token punctuation">(</span>childOb<span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
        childOb<span class="token punctuation">.</span>dep<span class="token punctuation">.</span><span class="token function">depend</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>Array<span class="token punctuation">.</span><span class="token function">isArray</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
          <span class="token function">dependArray</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
      <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> value<span class="token punctuation">;</span>
  <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">,</span>
  <span class="token keyword">set</span><span class="token punctuation">:</span> <span class="token keyword">function</span> <span class="token function">reactiveSetter</span><span class="token punctuation">(</span>newVal<span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    <span class="token keyword">const</span> value <span class="token operator">=</span> getter <span class="token operator">?</span> getter<span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span>obj<span class="token punctuation">)</span> <span class="token punctuation">:</span> val<span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>newVal <span class="token operator">===</span> value <span class="token operator">||</span> <span class="token punctuation">(</span>newVal <span class="token operator">!==</span> newVal <span class="token operator">&amp;&amp;</span> value <span class="token operator">!==</span> value<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
      <span class="token keyword">return</span><span class="token punctuation">;</span>
    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>process<span class="token punctuation">.</span>env<span class="token punctuation">.</span>NODE_ENV <span class="token operator">!==</span> <span class="token string">"production"</span> <span class="token operator">&amp;&amp;</span> customSetter<span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
      <span class="token function">customSetter</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
    val <span class="token operator">=</span> newVal<span class="token punctuation">;</span>
    childOb <span class="token operator">=</span> <span class="token operator">!</span>shallow <span class="token operator">&amp;&amp;</span> <span class="token function">observe</span><span class="token punctuation">(</span>newVal<span class="token punctuation">)</span><span class="token punctuation">;</span>
    dep<span class="token punctuation">.</span><span class="token function">notify</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">/**通知相关依赖进行更新**/</span>
  <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">,</span>
<span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h4 id="29-Vue中是如何检测数组变化"><a href="#29-Vue中是如何检测数组变化" class="headerlink" title="29.Vue中是如何检测数组变化?"></a>29.<code>Vue</code>中是如何检测数组变化?</h4><p>数组考虑性能原因没有用<code>defineProperty</code>对数组的每一项进行拦截，而是选择重写数组 方法以进行重写。</p>
<p>当数组调用到这 7 个方法的时候，执行 <code>ob.dep.notify()</code> 进行派发通知 <code>Watcher</code> 更新；</p>
<p>在 Vue 中修改数组的索引和长度是无法监控到的。</p>
<p>需要通过以下 7 种变异方法修改数组才会触发数组对应的<code>wacther</code>进行更新。</p>
<p>数组中如果是对象数据类型也会进行递归劫持。</p>
<h4 id="说明：那如果想要改索引更新数据怎么办？"><a href="#说明：那如果想要改索引更新数据怎么办？" class="headerlink" title="说明：那如果想要改索引更新数据怎么办？"></a>说明：那如果想要改索引更新数据怎么办？</h4><p>可以通过<code>Vue.set()</code>来进行处理 =》 核心内部用的是 <code>splice</code> 方法。</p>
<h4 id="源码"><a href="#源码" class="headerlink" title="源码"></a>源码</h4><pre class=" language-javascript"><code class="language-javascript"><span class="token keyword">const</span> arrayProto <span class="token operator">=</span> Array<span class="token punctuation">.</span>prototype<span class="token punctuation">;</span>
<span class="token keyword">export</span> <span class="token keyword">const</span> arrayMethods <span class="token operator">=</span> Object<span class="token punctuation">.</span><span class="token function">create</span><span class="token punctuation">(</span>arrayProto<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> methodsToPatch <span class="token operator">=</span> <span class="token punctuation">[</span>
  <span class="token string">"push"</span><span class="token punctuation">,</span>
  <span class="token string">"pop"</span><span class="token punctuation">,</span>
  <span class="token string">"shift"</span><span class="token punctuation">,</span>
  <span class="token string">"unshift"</span><span class="token punctuation">,</span>
  <span class="token string">"splice"</span><span class="token punctuation">,</span>
  <span class="token string">"sort"</span><span class="token punctuation">,</span>
  <span class="token string">"reverse"</span><span class="token punctuation">,</span>
<span class="token punctuation">]</span><span class="token punctuation">;</span>
methodsToPatch<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span>method<span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
  <span class="token comment" spellcheck="true">// 重写原型方法</span>
  <span class="token keyword">const</span> original <span class="token operator">=</span> arrayProto<span class="token punctuation">[</span>method<span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">// 调用原数组的方法</span>
  <span class="token function">def</span><span class="token punctuation">(</span>arrayMethods<span class="token punctuation">,</span> method<span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token function">mutator</span><span class="token punctuation">(</span><span class="token operator">...</span>args<span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    <span class="token keyword">const</span> result <span class="token operator">=</span> original<span class="token punctuation">.</span><span class="token function">apply</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">,</span> args<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">const</span> ob <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>__ob__<span class="token punctuation">;</span>
    <span class="token keyword">let</span> inserted<span class="token punctuation">;</span>
    <span class="token keyword">switch</span> <span class="token punctuation">(</span>method<span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
      <span class="token keyword">case</span> <span class="token string">"push"</span><span class="token punctuation">:</span>
      <span class="token keyword">case</span> <span class="token string">"unshift"</span><span class="token punctuation">:</span>
        inserted <span class="token operator">=</span> args<span class="token punctuation">;</span>
        <span class="token keyword">break</span><span class="token punctuation">;</span>
      <span class="token keyword">case</span> <span class="token string">"splice"</span><span class="token punctuation">:</span>
        inserted <span class="token operator">=</span> args<span class="token punctuation">.</span><span class="token function">slice</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">break</span><span class="token punctuation">;</span>
    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>inserted<span class="token punctuation">)</span> ob<span class="token punctuation">.</span><span class="token function">observeArray</span><span class="token punctuation">(</span>inserted<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token comment" spellcheck="true">// notify change</span>
    ob<span class="token punctuation">.</span>dep<span class="token punctuation">.</span><span class="token function">notify</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">// 当调用数组方法后，手动通知视图更新</span>
    <span class="token keyword">return</span> result<span class="token punctuation">;</span>
  <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">observeArray</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">// 进行深度监控</span></code></pre>
<h4 id="30-Vue-set-方法是如何实现的？"><a href="#30-Vue-set-方法是如何实现的？" class="headerlink" title="30.Vue.set 方法是如何实现的？"></a>30.<code>Vue.set</code> 方法是如何实现的？</h4><h3 id="核心答案"><a href="#核心答案" class="headerlink" title="核心答案"></a>核心答案</h3><p>为什么<code>$set</code>可以触发更新，我们给对象和数组本身都增加了<code>dep</code>属性，当给对象新增不存在的属性则触发对象依赖的<code>watcher</code>去更新，当修改数组索引时我们调用数组本身的<code>splice</code>方法去更新数组。</p>
<h3 id="补充答案"><a href="#补充答案" class="headerlink" title="补充答案"></a>补充答案</h3><ol>
<li>如果是数组，调用重写的 splice 方法 （这样可以更新视图 ）<br>代码：</li>
</ol>
<pre><code>target.splice(key, 1, val)</code></pre>
<ol start="2">
<li>如果不是响应式的也不需要将其定义成响应式属性。</li>
<li>如果是对象，将属性定义成响应式的</li>
</ol>
<pre><code>defineReactive(ob.value, key, val)</code></pre>
<h3 id="源码地址"><a href="#源码地址" class="headerlink" title="源码地址"></a>源码地址</h3><pre class=" language-javascript"><code class="language-javascript"><span class="token keyword">export</span> <span class="token keyword">function</span> <span class="token keyword">set</span><span class="token punctuation">(</span>target<span class="token punctuation">:</span> Array<span class="token operator">&lt;</span>any<span class="token operator">></span> <span class="token operator">|</span> Object<span class="token punctuation">,</span> key<span class="token punctuation">:</span> any<span class="token punctuation">,</span> val<span class="token punctuation">:</span> any<span class="token punctuation">)</span><span class="token punctuation">:</span> any <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>
    process<span class="token punctuation">.</span>env<span class="token punctuation">.</span>NODE_ENV <span class="token operator">!==</span> <span class="token string">"production"</span> <span class="token operator">&amp;&amp;</span>
    <span class="token punctuation">(</span><span class="token function">isUndef</span><span class="token punctuation">(</span>target<span class="token punctuation">)</span> <span class="token operator">||</span> <span class="token function">isPrimitive</span><span class="token punctuation">(</span>target<span class="token punctuation">)</span><span class="token punctuation">)</span>
  <span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    <span class="token function">warn</span><span class="token punctuation">(</span>
      <span class="token template-string"><span class="token string">`Cannot set reactive property on undefined, null, or primitive value: $&amp;#123;(target: any)&amp;#125;`</span></span>
    <span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>Array<span class="token punctuation">.</span><span class="token function">isArray</span><span class="token punctuation">(</span>target<span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> <span class="token function">isValidArrayIndex</span><span class="token punctuation">(</span>key<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    target<span class="token punctuation">.</span>length <span class="token operator">=</span> Math<span class="token punctuation">.</span><span class="token function">max</span><span class="token punctuation">(</span>target<span class="token punctuation">.</span>length<span class="token punctuation">,</span> key<span class="token punctuation">)</span><span class="token punctuation">;</span>
    target<span class="token punctuation">.</span><span class="token function">splice</span><span class="token punctuation">(</span>key<span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> val<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> val<span class="token punctuation">;</span>
  <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>key <span class="token keyword">in</span> target <span class="token operator">&amp;&amp;</span> <span class="token operator">!</span><span class="token punctuation">(</span>key <span class="token keyword">in</span> Object<span class="token punctuation">.</span>prototype<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    target<span class="token punctuation">[</span>key<span class="token punctuation">]</span> <span class="token operator">=</span> val<span class="token punctuation">;</span>
    <span class="token keyword">return</span> val<span class="token punctuation">;</span>
  <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> ob <span class="token operator">=</span> <span class="token punctuation">(</span>target<span class="token punctuation">:</span> any<span class="token punctuation">)</span><span class="token punctuation">.</span>__ob__<span class="token punctuation">;</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>target<span class="token punctuation">.</span>_isVue <span class="token operator">||</span> <span class="token punctuation">(</span>ob <span class="token operator">&amp;&amp;</span> ob<span class="token punctuation">.</span>vmCount<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    process<span class="token punctuation">.</span>env<span class="token punctuation">.</span>NODE_ENV <span class="token operator">!==</span> <span class="token string">"production"</span> <span class="token operator">&amp;&amp;</span>
      <span class="token function">warn</span><span class="token punctuation">(</span>
        <span class="token string">"Avoid adding reactive properties to a Vue instance or its root $data "</span> <span class="token operator">+</span>
          <span class="token string">"at runtime - declare it upfront in the data option."</span>
      <span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> val<span class="token punctuation">;</span>
  <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>ob<span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    target<span class="token punctuation">[</span>key<span class="token punctuation">]</span> <span class="token operator">=</span> val<span class="token punctuation">;</span>
    <span class="token keyword">return</span> val<span class="token punctuation">;</span>
  <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
  <span class="token function">defineReactive</span><span class="token punctuation">(</span>ob<span class="token punctuation">.</span>value<span class="token punctuation">,</span> key<span class="token punctuation">,</span> val<span class="token punctuation">)</span><span class="token punctuation">;</span>
  ob<span class="token punctuation">.</span>dep<span class="token punctuation">.</span><span class="token function">notify</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">return</span> val<span class="token punctuation">;</span>
<span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span></code></pre>
<h4 id="31-Vue中模板编译原理"><a href="#31-Vue中模板编译原理" class="headerlink" title="31.Vue中模板编译原理?"></a>31.<code>Vue</code>中模板编译原理?</h4><h3 id="核心答案-1"><a href="#核心答案-1" class="headerlink" title="核心答案"></a>核心答案</h3><p>将<code>template</code>转换成<code>render</code>函数</p>
<h3 id="补充说明"><a href="#补充说明" class="headerlink" title="补充说明"></a>补充说明</h3><p>这里要注意的是我们在开发时尽量不要使用 template.</p>
<p>因为将 template 转化成 render 方法需要在运行时进行编译操作会有性能损耗，同时引用带有 complier 包的 vue 体积也会变大.</p>
<p>默认.vue 文件中的 template 处理是通过 vue-loader 来进行处理的并不是通过运行时的编译。</p>
<h3 id="流程如下"><a href="#流程如下" class="headerlink" title="流程如下"></a>流程如下</h3><ol>
<li><p>将 template 模板转换成 ast 语法树 - parserHTML</p>
</li>
<li><p>对静态语法做静态标记 - markUp</p>
</li>
<li><p>重新生成代码 - codeGen</p>
</li>
</ol>
<h3 id="源码地址-1"><a href="#源码地址-1" class="headerlink" title="源码地址"></a>源码地址</h3><pre class=" language-javascript"><code class="language-javascript"><span class="token keyword">function</span> baseCompile <span class="token punctuation">(</span>
  template<span class="token punctuation">:</span> string<span class="token punctuation">,</span>
  options<span class="token punctuation">:</span> CompilerOptions
<span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> ast <span class="token operator">=</span> <span class="token function">parse</span><span class="token punctuation">(</span>template<span class="token punctuation">.</span><span class="token function">trim</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> options<span class="token punctuation">)</span> <span class="token comment" spellcheck="true">// 1.将模板转化成ast语法树</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>options<span class="token punctuation">.</span>optimize <span class="token operator">!==</span> <span class="token boolean">false</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>           <span class="token comment" spellcheck="true">// 2.优化树</span>
    <span class="token function">optimize</span><span class="token punctuation">(</span>ast<span class="token punctuation">,</span> options<span class="token punctuation">)</span>
  <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> code <span class="token operator">=</span> <span class="token function">generate</span><span class="token punctuation">(</span>ast<span class="token punctuation">,</span> options<span class="token punctuation">)</span>         <span class="token comment" spellcheck="true">// 3.生成树</span>
  <span class="token keyword">return</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    ast<span class="token punctuation">,</span>
    render<span class="token punctuation">:</span> code<span class="token punctuation">.</span>render<span class="token punctuation">,</span>
    staticRenderFns<span class="token punctuation">:</span> code<span class="token punctuation">.</span>staticRenderFns
  <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
<span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> ncname <span class="token operator">=</span> <span class="token template-string"><span class="token string">`[a-zA-Z_][\\-\\.0-9_a-zA-Z]*`</span></span><span class="token punctuation">;</span>
<span class="token keyword">const</span> qnameCapture <span class="token operator">=</span> <span class="token template-string"><span class="token string">`((?:$&amp;#123;ncname&amp;#125;\\:)?$&amp;#123;ncname&amp;#125;)`</span></span><span class="token punctuation">;</span>
<span class="token keyword">const</span> startTagOpen <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">RegExp</span><span class="token punctuation">(</span><span class="token template-string"><span class="token string">`^&lt;$&amp;#123;qnameCapture&amp;#125;`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">// 标签开头的正则 捕获的内容是标签名</span>
<span class="token keyword">const</span> endTag <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">RegExp</span><span class="token punctuation">(</span><span class="token template-string"><span class="token string">`^&lt;\\/$&amp;#123;qnameCapture&amp;#125;[^>]*>`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">// 匹配标签结尾的  &lt;/div></span>
<span class="token keyword">const</span> attribute <span class="token operator">=</span> <span class="token operator">/</span><span class="token operator">^</span>\s<span class="token operator">*</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token operator">^</span>\s<span class="token string">"'&lt;>\/=]+)(?:\s*(=)\s*(?:"</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token operator">^</span><span class="token string">"]*)"</span><span class="token operator">+</span><span class="token operator">|</span><span class="token string">'([^'</span><span class="token punctuation">]</span><span class="token operator">*</span><span class="token punctuation">)</span><span class="token string">'+|([^\s"'</span><span class="token operator">=</span><span class="token operator">&lt;</span><span class="token operator">></span><span class="token template-string"><span class="token string">`]+)))?/; // 匹配属性的
const startTagClose = /^\s*(\/?)>/; // 匹配标签结束的  >
let root;
let currentParent;
let stack = []
function createASTElement(tagName,attrs)&amp;#123;
    return &amp;#123;
        tag:tagName,
        type:1,
        children:[],
        attrs,
        parent:null
    &amp;#125;
&amp;#125;
function start(tagName,attrs)&amp;#123;
    let element = createASTElement(tagName,attrs);
    if(!root)&amp;#123;
        root = element;
    &amp;#125;
    currentParent = element;
    stack.push(element);
&amp;#125;
function chars(text)&amp;#123;
    currentParent.children.push(&amp;#123;
        type:3,
        text
    &amp;#125;)
&amp;#125;
function end(tagName)&amp;#123;
    const element = stack[stack.length-1];
    stack.length --;
    currentParent = stack[stack.length-1];
    if(currentParent)&amp;#123;
        element.parent = currentParent;
        currentParent.children.push(element)
    &amp;#125;
&amp;#125;
function parseHTML(html)&amp;#123;
    while(html)&amp;#123;
        let textEnd = html.indexOf('&lt;');
        if(textEnd == 0)&amp;#123;
            const startTagMatch = parseStartTag();
            if(startTagMatch)&amp;#123;
                start(startTagMatch.tagName,startTagMatch.attrs);
                continue;
            &amp;#125;
            const endTagMatch = html.match(endTag);
            if(endTagMatch)&amp;#123;
                advance(endTagMatch[0].length);
                end(endTagMatch[1])
            &amp;#125;
        &amp;#125;
        let text;
        if(textEnd >=0 )&amp;#123;
            text = html.substring(0,textEnd)
        &amp;#125;
        if(text)&amp;#123;
            advance(text.length);
            chars(text);
        &amp;#125;
    &amp;#125;
    function advance(n) &amp;#123;
        html = html.substring(n);
    &amp;#125;
    function parseStartTag()&amp;#123;
        const start = html.match(startTagOpen);
        if(start)&amp;#123;
            const match = &amp;#123;
                tagName:start[1],
                attrs:[]
            &amp;#125;
            advance(start[0].length);
            let attr,end
            while(!(end = html.match(startTagClose)) &amp;&amp; (attr=html.match(attribute)))&amp;#123;
                advance(attr[0].length);
                match.attrs.push(&amp;#123;name:attr[1],value:attr[3]&amp;#125;)
            &amp;#125;
            if(end)&amp;#123;
                advance(end[0].length);
                return match
            &amp;#125;
        &amp;#125;
    &amp;#125;
&amp;#125;
// 生成语法树
parseHTML(`</span></span><span class="token operator">&lt;</span>div id<span class="token operator">=</span><span class="token string">"container"</span><span class="token operator">></span><span class="token operator">&lt;</span>p<span class="token operator">></span>hello<span class="token operator">&lt;</span>span<span class="token operator">></span>zf<span class="token operator">&lt;</span><span class="token operator">/</span>span<span class="token operator">></span><span class="token operator">&lt;</span><span class="token operator">/</span>p<span class="token operator">></span><span class="token operator">&lt;</span><span class="token operator">/</span>div<span class="token operator">></span><span class="token template-string"><span class="token string">`);
function gen(node)&amp;#123;
    if(node.type == 1)&amp;#123;
        return generate(node);
    &amp;#125;else&amp;#123;
        return `</span></span><span class="token function">_v</span><span class="token punctuation">(</span>$<span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>JSON<span class="token punctuation">.</span><span class="token function">stringify</span><span class="token punctuation">(</span>node<span class="token punctuation">.</span>text<span class="token punctuation">)</span><span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">)</span><span class="token template-string"><span class="token string">`
    &amp;#125;
&amp;#125;
function genChildren(el)&amp;#123;
    const children = el.children;
    if(el.children)&amp;#123;
        return `</span></span><span class="token punctuation">[</span>$<span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>children<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span>c<span class="token operator">=</span><span class="token operator">></span><span class="token function">gen</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">','</span><span class="token punctuation">)</span><span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">]</span><span class="token template-string"><span class="token string">`
    &amp;#125;else&amp;#123;
        return false;
    &amp;#125;
&amp;#125;
function genProps(attrs)&amp;#123;
    let str = '';
    for(let i = 0; i &lt; attrs.length;i++)&amp;#123;
        let attr = attrs[i];
        str+= `</span></span>$<span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>attr<span class="token punctuation">.</span>name<span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">:</span>$<span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>attr<span class="token punctuation">.</span>value<span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">,</span><span class="token template-string"><span class="token string">`;
    &amp;#125;
    return `</span></span><span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>attrs<span class="token punctuation">:</span><span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>$<span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>str<span class="token punctuation">.</span><span class="token function">slice</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token template-string"><span class="token string">`
&amp;#125;
function generate(el)&amp;#123;
    let children = genChildren(el);
    let code = `</span></span><span class="token function">_c</span><span class="token punctuation">(</span><span class="token string">'$&amp;#123;el.tag&amp;#125;'</span>$<span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
        el<span class="token punctuation">.</span>attrs<span class="token punctuation">.</span>length<span class="token operator">?</span> <span class="token template-string"><span class="token string">`,$&amp;#123;genProps(el.attrs)&amp;#125;`</span></span><span class="token punctuation">:</span><span class="token string">''</span>
    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>$<span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
        children<span class="token operator">?</span> <span class="token template-string"><span class="token string">`,$&amp;#123;children&amp;#125;`</span></span><span class="token punctuation">:</span><span class="token string">''</span>
    <span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token punctuation">)</span><span class="token template-string"><span class="token string">`;
    return code;
&amp;#125;
// 根据语法树生成新的代码
let code = generate(root);
let render = `</span></span><span class="token keyword">with</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span><span class="token keyword">return</span> $<span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>code<span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span><span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>`<span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">// 包装成函数</span>
<span class="token keyword">let</span> renderFn <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Function</span><span class="token punctuation">(</span>render<span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>renderFn<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h4 id="32-Proxy-与-Object-defineProperty-优劣对比"><a href="#32-Proxy-与-Object-defineProperty-优劣对比" class="headerlink" title="32.Proxy 与 Object.defineProperty 优劣对比?"></a>32.<code>Proxy</code> 与 <code>Object.defineProperty</code> 优劣对比?</h4><h3 id="Proxy-的优势如下"><a href="#Proxy-的优势如下" class="headerlink" title="Proxy 的优势如下:"></a>Proxy 的优势如下:</h3><p>1）<code>Proxy</code> 可以直接监听对象而非属性；</p>
<p>2）<code>Proxy</code> 可以直接监听数组的变化；</p>
<p>3）<code>Proxy</code> 有多达 13 种拦截方法,不限于 apply、ownKeys、deleteProperty、has 等等是 Object.defineProperty 不具备的；</p>
<p>4）<code>Proxy</code> 返回的是一个新对象,我们可以只操作新的对象达到目的,而 Object.defineProperty 只能遍历对象属性直接修改；</p>
<p>5）Proxy 作为新标准将受到浏览器厂商重点持续的性能优化，也就是传说中的新标准的性能红利；</p>
<h3 id="Object-defineProperty-的优势如下"><a href="#Object-defineProperty-的优势如下" class="headerlink" title="Object.defineProperty 的优势如下:"></a>Object.defineProperty 的优势如下:</h3><p>兼容性好，支持 IE9，而 Proxy 的存在浏览器兼容性问题，而且无法用 polyfill 磨平，因此 Vue 的作者才声明需要等到下个大版本( 3.0 )才能用 Proxy 重写。</p>
<h4 id="33-Vue3-x响应式数据原理"><a href="#33-Vue3-x响应式数据原理" class="headerlink" title="33.Vue3.x响应式数据原理?"></a>33.<code>Vue3.x</code>响应式数据原理?</h4><p><code>Vue3.x</code>改用<code>Proxy</code>替代<code>Object.defineProperty</code>。</p>
<p>因为<code>Proxy</code>可以直接监听对象和数组的变化，并且有多达 13 种拦截方法。并且作为新标准将受到浏览器厂商重点持续的性能优化。</p>
<p><code>Proxy</code>只会代理对象的第一层，那么<code>Vue3</code>又是怎样处理这个问题的呢？<br>判断当前<code>Reflect.get</code>的返回值是否为<code>Object</code>，如果是则再通过<code>reactive</code>方法做代理， 这样就实现了深度观测。</p>
<p>监测数组的时候可能触发多次<code>get/set</code>，那么如何防止触发多次呢？<br>我们可以判断<code>key</code>是否为当前被代理对象<code>target</code>自身属性，也可以判断旧值与新值是否相等，只有满足以上两个条件之一时，才有可能执行<code>trigger</code>。</p>
<h4 id="34-Vue的生命周期方法有哪些？"><a href="#34-Vue的生命周期方法有哪些？" class="headerlink" title="34.Vue的生命周期方法有哪些？"></a>34.<code>Vue</code>的生命周期方法有哪些？</h4><blockquote>
<p>总共分为 8 个阶段：创建前/后，载入前/后，更新前/后，销毁前/后。</p>
</blockquote>
<h3 id="1､创建前-后："><a href="#1､创建前-后：" class="headerlink" title="1､创建前/后："></a>1､创建前/后：</h3><ol>
<li><code>beforeCreate</code>阶段：<code>vue</code>实例的挂载元素<code>el</code>和数据对象<code>data</code>都为<code>undefined</code>，还未初始化。</li>
</ol>
<p>说明：在当前阶段 data、methods、computed 以及 watch 上的数据和方法都不能被访问。</p>
<ol start="2">
<li>created 阶段：vue 实例的数据对象 data 有了，el 还没有。</li>
</ol>
<p>说明：可以做一些初始数据的获取，在当前阶段无法与 Dom 进行交互，如果非要想，可以通过 vm.$nextTick 来访问 Dom。</p>
<h3 id="2､载入前-后："><a href="#2､载入前-后：" class="headerlink" title="2､载入前/后："></a>2､载入前/后：</h3><ol>
<li><p>beforeMount 阶段：vue 实例的$el 和 data 都初始化了，但还是挂载之前为虚拟的 dom 节点。<br>说明：当前阶段虚拟 Dom 已经创建完成，即将开始渲染。在此时也可以对数据进行更改，不会触发 updated。</p>
</li>
<li><p>mounted 阶段：vue 实例挂载完成，data.message 成功渲染。</p>
</li>
</ol>
<p>说明：在当前阶段，真实的 Dom 挂载完毕，数据完成双向绑定，可以访问到 Dom 节点，使用$refs 属性对 Dom 进行操作。</p>
<h2 id="3､更新前-后："><a href="#3､更新前-后：" class="headerlink" title="3､更新前/后："></a>3､更新前/后：</h2><ol>
<li>beforeUpdate 阶段：响应式数据更新时调用，发生在虚拟 DOM 打补丁之前，适合在更新之前访问现有的 DOM，比如手动移除已添加的事件监听器。</li>
</ol>
<p>说明：可以在当前阶段进行更改数据，不会造成重渲染。</p>
<ol start="2">
<li>updated 阶段：虚拟 DOM 重新渲染和打补丁之后调用，组成新的 DOM 已经更新，避免在这个钩子函数中操作数据，防止死循环。</li>
</ol>
<p>说明：当前阶段组件 Dom 已完成更新。要注意的是避免在此期间更改数据，因为这可能会导致无限循环的更新。</p>
<h2 id="4､销毁前-后："><a href="#4､销毁前-后：" class="headerlink" title="4､销毁前/后："></a>4､销毁前/后：</h2><ol>
<li>beforeDestroy 阶段：实例销毁前调用，实例还可以用，this 能获取到实例，常用于销毁定时器，解绑事件。</li>
</ol>
<p>说明：在当前阶段实例完全可以被使用，我们可以在这时进行善后收尾工作，比如清除计时器。</p>
<ol start="2">
<li>destroyed 阶段：实例销毁后调用，调用后所有事件监听器会被移除，所有的子实例都会被销毁。</li>
</ol>
<p>说明：当前阶段组件已被拆解，数据绑定被卸除，监听被移出，子实例也统统被销毁。</p>
<h3 id="补充说明-1"><a href="#补充说明-1" class="headerlink" title="补充说明"></a>补充说明</h3><p>第一次页面加载时会触发：beforeCreate, created, beforeMount, mounted。</p>
<ol>
<li><p>created 实例已经创建完成，因为它是最早触发的原因可以进行一些数据，资源的请求。(服务器渲染支持 created 方法)</p>
</li>
<li><p>mounted 实例已经挂载完成，可以进行一些 DOM 操作。(接口请求)</p>
</li>
</ol>
<h3 id="生命周期图"><a href="#生命周期图" class="headerlink" title="生命周期图"></a>生命周期图</h3><p><img src="https://yangyunhaiimagesoss.oss-cn-shanghai.aliyuncs.com/2011101150_1604980206089.png"></p>
<h4 id="源码-1"><a href="#源码-1" class="headerlink" title="源码"></a>源码</h4><pre class=" language-javaScript"><code class="language-javaScript">/* @flow */

import config from "../config";
import Watcher from "../observer/watcher";
import &#123; mark, measure &#125; from "../util/perf";
import &#123; createEmptyVNode &#125; from "../vdom/vnode";
import &#123; updateComponentListeners &#125; from "./events";
import &#123; resolveSlots &#125; from "./render-helpers/resolve-slots";
import &#123; toggleObserving &#125; from "../observer/index";
import &#123; pushTarget, popTarget &#125; from "../observer/dep";

import &#123;
  warn,
  noop,
  remove,
  emptyObject,
  validateProp,
  invokeWithErrorHandling,
&#125; from "../util/index";

export let activeInstance: any = null;
export let isUpdatingChildComponent: boolean = false;

export function setActiveInstance(vm: Component) &#123;
  const prevActiveInstance = activeInstance;
  activeInstance = vm;
  return () => &#123;
    activeInstance = prevActiveInstance;
  &#125;;
&#125;

export function initLifecycle(vm: Component) &#123;
  const options = vm.$options;

  // locate first non-abstract parent
  let parent = options.parent;
  if (parent && !options.abstract) &#123;
    while (parent.$options.abstract && parent.$parent) &#123;
      parent = parent.$parent;
    &#125;
    parent.$children.push(vm);
  &#125;

  vm.$parent = parent;
  vm.$root = parent ? parent.$root : vm;

  vm.$children = [];
  vm.$refs = &#123;&#125;;

  vm._watcher = null;
  vm._inactive = null;
  vm._directInactive = false;
  vm._isMounted = false;
  vm._isDestroyed = false;
  vm._isBeingDestroyed = false;
&#125;

export function lifecycleMixin(Vue: Class<Component>) &#123;
  Vue.prototype._update = function (vnode: VNode, hydrating?: boolean) &#123;
    const vm: Component = this;
    const prevEl = vm.$el;
    const prevVnode = vm._vnode;
    const restoreActiveInstance = setActiveInstance(vm);
    vm._vnode = vnode;
    // Vue.prototype.__patch__ is injected in entry points
    // based on the rendering backend used.
    if (!prevVnode) &#123;
      // initial render
      vm.$el = vm.__patch__(vm.$el, vnode, hydrating, false /* removeOnly */);
    &#125; else &#123;
      // updates
      vm.$el = vm.__patch__(prevVnode, vnode);
    &#125;
    restoreActiveInstance();
    // update __vue__ reference
    if (prevEl) &#123;
      prevEl.__vue__ = null;
    &#125;
    if (vm.$el) &#123;
      vm.$el.__vue__ = vm;
    &#125;
    // if parent is an HOC, update its $el as well
    if (vm.$vnode && vm.$parent && vm.$vnode === vm.$parent._vnode) &#123;
      vm.$parent.$el = vm.$el;
    &#125;
    // updated hook is called by the scheduler to ensure that children are
    // updated in a parent's updated hook.
  &#125;;

  Vue.prototype.$forceUpdate = function () &#123;
    const vm: Component = this;
    if (vm._watcher) &#123;
      vm._watcher.update();
    &#125;
  &#125;;

  Vue.prototype.$destroy = function () &#123;
    const vm: Component = this;
    if (vm._isBeingDestroyed) &#123;
      return;
    &#125;
    callHook(vm, "beforeDestroy");
    vm._isBeingDestroyed = true;
    // remove self from parent
    const parent = vm.$parent;
    if (parent && !parent._isBeingDestroyed && !vm.$options.abstract) &#123;
      remove(parent.$children, vm);
    &#125;
    // teardown watchers
    if (vm._watcher) &#123;
      vm._watcher.teardown();
    &#125;
    let i = vm._watchers.length;
    while (i--) &#123;
      vm._watchers[i].teardown();
    &#125;
    // remove reference from data ob
    // frozen object may not have observer.
    if (vm._data.__ob__) &#123;
      vm._data.__ob__.vmCount--;
    &#125;
    // call the last hook...
    vm._isDestroyed = true;
    // invoke destroy hooks on current rendered tree
    vm.__patch__(vm._vnode, null);
    // fire destroyed hook
    callHook(vm, "destroyed");
    // turn off all instance listeners.
    vm.$off();
    // remove __vue__ reference
    if (vm.$el) &#123;
      vm.$el.__vue__ = null;
    &#125;
    // release circular reference (#6759)
    if (vm.$vnode) &#123;
      vm.$vnode.parent = null;
    &#125;
  &#125;;
&#125;

export function mountComponent(
  vm: Component,
  el: ?Element,
  hydrating?: boolean
): Component &#123;
  vm.$el = el;
  if (!vm.$options.render) &#123;
    vm.$options.render = createEmptyVNode;
    if (process.env.NODE_ENV !== "production") &#123;
      /* istanbul ignore if */
      if (
        (vm.$options.template && vm.$options.template.charAt(0) !== "#") ||
        vm.$options.el ||
        el
      ) &#123;
        warn(
          "You are using the runtime-only build of Vue where the template " +
            "compiler is not available. Either pre-compile the templates into " +
            "render functions, or use the compiler-included build.",
          vm
        );
      &#125; else &#123;
        warn(
          "Failed to mount component: template or render function not defined.",
          vm
        );
      &#125;
    &#125;
  &#125;
  callHook(vm, "beforeMount");

  let updateComponent;
  /* istanbul ignore if */
  if (process.env.NODE_ENV !== "production" && config.performance && mark) &#123;
    updateComponent = () => &#123;
      const name = vm._name;
      const id = vm._uid;
      const startTag = `vue-perf-start:$&#123;id&#125;`;
      const endTag = `vue-perf-end:$&#123;id&#125;`;

      mark(startTag);
      const vnode = vm._render();
      mark(endTag);
      measure(`vue $&#123;name&#125; render`, startTag, endTag);

      mark(startTag);
      vm._update(vnode, hydrating);
      mark(endTag);
      measure(`vue $&#123;name&#125; patch`, startTag, endTag);
    &#125;;
  &#125; else &#123;
    updateComponent = () => &#123;
      vm._update(vm._render(), hydrating);
    &#125;;
  &#125;

  // we set this to vm._watcher inside the watcher's constructor
  // since the watcher's initial patch may call $forceUpdate (e.g. inside child
  // component's mounted hook), which relies on vm._watcher being already defined
  new Watcher(
    vm,
    updateComponent,
    noop,
    &#123;
      before() &#123;
        if (vm._isMounted && !vm._isDestroyed) &#123;
          callHook(vm, "beforeUpdate");
        &#125;
      &#125;,
    &#125;,
    true /* isRenderWatcher */
  );
  hydrating = false;

  // manually mounted instance, call mounted on self
  // mounted is called for render-created child components in its inserted hook
  if (vm.$vnode == null) &#123;
    vm._isMounted = true;
    callHook(vm, "mounted");
  &#125;
  return vm;
&#125;

export function updateChildComponent(
  vm: Component,
  propsData: ?Object,
  listeners: ?Object,
  parentVnode: MountedComponentVNode,
  renderChildren: ?Array<VNode>
) &#123;
  if (process.env.NODE_ENV !== "production") &#123;
    isUpdatingChildComponent = true;
  &#125;

  // determine whether component has slot children
  // we need to do this before overwriting $options._renderChildren.

  // check if there are dynamic scopedSlots (hand-written or compiled but with
  // dynamic slot names). Static scoped slots compiled from template has the
  // "$stable" marker.
  const newScopedSlots = parentVnode.data.scopedSlots;
  const oldScopedSlots = vm.$scopedSlots;
  const hasDynamicScopedSlot = !!(
    (newScopedSlots && !newScopedSlots.$stable) ||
    (oldScopedSlots !== emptyObject && !oldScopedSlots.$stable) ||
    (newScopedSlots && vm.$scopedSlots.$key !== newScopedSlots.$key)
  );

  // Any static slot children from the parent may have changed during parent's
  // update. Dynamic scoped slots may also have changed. In such cases, a forced
  // update is necessary to ensure correctness.
  const needsForceUpdate = !!(
    renderChildren || // has new static slots
    vm.$options._renderChildren || // has old static slots
    hasDynamicScopedSlot
  );

  vm.$options._parentVnode = parentVnode;
  vm.$vnode = parentVnode; // update vm's placeholder node without re-render

  if (vm._vnode) &#123;
    // update child tree's parent
    vm._vnode.parent = parentVnode;
  &#125;
  vm.$options._renderChildren = renderChildren;

  // update $attrs and $listeners hash
  // these are also reactive so they may trigger child update if the child
  // used them during render
  vm.$attrs = parentVnode.data.attrs || emptyObject;
  vm.$listeners = listeners || emptyObject;

  // update props
  if (propsData && vm.$options.props) &#123;
    toggleObserving(false);
    const props = vm._props;
    const propKeys = vm.$options._propKeys || [];
    for (let i = 0; i < propKeys.length; i++) &#123;
      const key = propKeys[i];
      const propOptions: any = vm.$options.props; // wtf flow?
      props[key] = validateProp(key, propOptions, propsData, vm);
    &#125;
    toggleObserving(true);
    // keep a copy of raw propsData
    vm.$options.propsData = propsData;
  &#125;

  // update listeners
  listeners = listeners || emptyObject;
  const oldListeners = vm.$options._parentListeners;
  vm.$options._parentListeners = listeners;
  updateComponentListeners(vm, listeners, oldListeners);

  // resolve slots + force update if has children
  if (needsForceUpdate) &#123;
    vm.$slots = resolveSlots(renderChildren, parentVnode.context);
    vm.$forceUpdate();
  &#125;

  if (process.env.NODE_ENV !== "production") &#123;
    isUpdatingChildComponent = false;
  &#125;
&#125;

function isInInactiveTree(vm) &#123;
  while (vm && (vm = vm.$parent)) &#123;
    if (vm._inactive) return true;
  &#125;
  return false;
&#125;

export function activateChildComponent(vm: Component, direct?: boolean) &#123;
  if (direct) &#123;
    vm._directInactive = false;
    if (isInInactiveTree(vm)) &#123;
      return;
    &#125;
  &#125; else if (vm._directInactive) &#123;
    return;
  &#125;
  if (vm._inactive || vm._inactive === null) &#123;
    vm._inactive = false;
    for (let i = 0; i < vm.$children.length; i++) &#123;
      activateChildComponent(vm.$children[i]);
    &#125;
    callHook(vm, "activated");
  &#125;
&#125;

export function deactivateChildComponent(vm: Component, direct?: boolean) &#123;
  if (direct) &#123;
    vm._directInactive = true;
    if (isInInactiveTree(vm)) &#123;
      return;
    &#125;
  &#125;
  if (!vm._inactive) &#123;
    vm._inactive = true;
    for (let i = 0; i < vm.$children.length; i++) &#123;
      deactivateChildComponent(vm.$children[i]);
    &#125;
    callHook(vm, "deactivated");
  &#125;
&#125;

export function callHook(vm: Component, hook: string) &#123;
  // #7573 disable dep collection when invoking lifecycle hooks
  pushTarget();
  const handlers = vm.$options[hook];
  const info = `$&#123;hook&#125; hook`;
  if (handlers) &#123;
    for (let i = 0, j = handlers.length; i < j; i++) &#123;
      invokeWithErrorHandling(handlers[i], vm, null, vm, info);
    &#125;
  &#125;
  if (vm._hasHookEvent) &#123;
    vm.$emit("hook:" + hook);
  &#125;
  popTarget();
&#125;</code></pre>
<h4 id="35-生命周期钩子是如何实现的"><a href="#35-生命周期钩子是如何实现的" class="headerlink" title="35.生命周期钩子是如何实现的?"></a>35.生命周期钩子是如何实现的?</h4><h4 id="核心答案：-2"><a href="#核心答案：-2" class="headerlink" title="核心答案："></a>核心答案：</h4><p>Vue 的生命周期钩子就是回调函数而已，当创建组件实例的过程中会调用对应的钩子方法。</p>
<h4 id="补充说明-2"><a href="#补充说明-2" class="headerlink" title="补充说明"></a>补充说明</h4><p>内部主要是使用 callHook 方法来调用对应的方法。核心是一个发布订阅模式，将钩子订阅好(内部采用数组的方式存储)，在对应的阶段进行发布。</p>
<h4 id="36-Vue-的父组件和子组件生命周期钩子执行顺序"><a href="#36-Vue-的父组件和子组件生命周期钩子执行顺序" class="headerlink" title="36.Vue 的父组件和子组件生命周期钩子执行顺序?"></a>36.<code>Vue</code> 的父组件和子组件生命周期钩子执行顺序?</h4><h3 id="核心答案：-3"><a href="#核心答案：-3" class="headerlink" title="核心答案："></a>核心答案：</h3><p>第一次页面加载时会触发 beforeCreate, created, beforeMount, mounted 这几个钩子。</p>
<h3 id="渲染过程："><a href="#渲染过程：" class="headerlink" title="渲染过程："></a>渲染过程：</h3><p>父组件挂载完成一定是等子组件都挂载完成后，才算是父组件挂载完，所以父组件的 mounted 在子组件 mouted 之后</p>
<ul>
<li>父 beforeCreate -&gt;</li>
<li>父 created -&gt;</li>
<li>父 beforeMount -&gt;</li>
<li>子 beforeCreate -&gt;</li>
<li>子 created -&gt;</li>
<li>子 beforeMount -&gt;</li>
<li>子 mounted -&gt;</li>
<li>父 mounted</li>
</ul>
<h3 id="子组件更新过程："><a href="#子组件更新过程：" class="headerlink" title="子组件更新过程："></a>子组件更新过程：</h3><p>影响到父组件：</p>
<ul>
<li>父 beforeUpdate -&gt;</li>
<li>子 beforeUpdate-&gt;</li>
<li>子 updated -&gt;</li>
<li>父 updted</li>
</ul>
<p>不影响父组件：</p>
<ul>
<li>子 beforeUpdate -&gt;</li>
<li>子 updated</li>
</ul>
<h3 id="父组件更新过程："><a href="#父组件更新过程：" class="headerlink" title="父组件更新过程："></a>父组件更新过程：</h3><p>影响到子组件：</p>
<ul>
<li>父 beforeUpdate -&gt;</li>
<li>子 beforeUpdate-&gt;</li>
<li>子 updated -&gt;</li>
<li>父 updted</li>
</ul>
<p>不影响子组件：</p>
<ul>
<li>父 beforeUpdate -&gt;</li>
<li>父 updated</li>
</ul>
<h3 id="销毁过程："><a href="#销毁过程：" class="headerlink" title="销毁过程："></a>销毁过程：</h3><ul>
<li>父 beforeDestroy -&gt;</li>
<li>子 beforeDestroy -&gt;</li>
<li>子 destroyed -&gt;</li>
<li>父 destroyed</li>
</ul>
<blockquote>
<p>重要：父组件等待子组件完成后，才会执行自己对应完成的钩子。</p>
</blockquote>
<h4 id="37-组件中写-name选项有哪些好处及作用？"><a href="#37-组件中写-name选项有哪些好处及作用？" class="headerlink" title="37.组件中写 name选项有哪些好处及作用？"></a>37.组件中写 <code>name</code>选项有哪些好处及作用？</h4><h3 id="核心答案：-4"><a href="#核心答案：-4" class="headerlink" title="核心答案："></a>核心答案：</h3><ol>
<li>可以通过名字找到对应的组件 （ 递归组件 ）</li>
<li>可以通过 name 属性实现缓存功能 (keep-alive)</li>
<li>可以通过 name 来识别组件 （跨级组件通信时非常重要）</li>
</ol>
<h3 id="源码-2"><a href="#源码-2" class="headerlink" title="源码"></a>源码</h3><pre class=" language-javaScript"><code class="language-javaScript">Vue.extend = function () &#123;
  if (name) &#123;
    Sub.options.componentd[name] = Sub;
  &#125;
&#125;;</code></pre>
<h4 id="38-keep-alive平时在哪里使用？原理是？"><a href="#38-keep-alive平时在哪里使用？原理是？" class="headerlink" title="38.keep-alive平时在哪里使用？原理是？"></a>38.<code>keep-alive</code>平时在哪里使用？原理是？</h4><h3 id="核心答案：-5"><a href="#核心答案：-5" class="headerlink" title="核心答案："></a>核心答案：</h3><p>keep-alive 主要是组件缓存，采用的是 LRU 算法。最近最久未使用法。</p>
<p>常用的两个属性 include/exclude，允许组件有条件的进行缓存。</p>
<p>两个生命周期 activated/deactivated，用来得知当前组件是否处于活跃状态。</p>
<h3 id="源码-3"><a href="#源码-3" class="headerlink" title="源码"></a>源码</h3><pre class=" language-javascript"><code class="language-javascript">abstract<span class="token punctuation">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span> <span class="token comment" spellcheck="true">// 抽象组件</span>
props<span class="token punctuation">:</span><span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    include<span class="token punctuation">:</span> patternTypes<span class="token punctuation">,</span>  <span class="token comment" spellcheck="true">// 要缓存的有哪些</span>
    exclude<span class="token punctuation">:</span> patternTypes<span class="token punctuation">,</span> <span class="token comment" spellcheck="true">// 要排除的有哪些</span>
    max<span class="token punctuation">:</span> <span class="token punctuation">[</span>String<span class="token punctuation">,</span> Number<span class="token punctuation">]</span> <span class="token comment" spellcheck="true">//最大缓存数量</span>
<span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
<span class="token keyword">if</span><span class="token punctuation">(</span>cache<span class="token punctuation">[</span>key<span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">// 通过key 找到缓存，获取实例</span>
    vnode<span class="token punctuation">.</span>componentInstance <span class="token operator">=</span> cache<span class="token punctuation">[</span>key<span class="token punctuation">]</span><span class="token punctuation">.</span>componentInstance
    <span class="token function">remove</span><span class="token punctuation">(</span>keys<span class="token punctuation">,</span> key<span class="token punctuation">)</span> <span class="token comment" spellcheck="true">//将key删除掉</span>
    keys<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span>key<span class="token punctuation">)</span> <span class="token comment" spellcheck="true">// 放到末尾</span>
<span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span> <span class="token keyword">else</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span>
    cache<span class="token punctuation">[</span>key<span class="token punctuation">]</span> <span class="token operator">=</span> vnode <span class="token comment" spellcheck="true">// 没有缓存过</span>
    keys<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span>key<span class="token punctuation">)</span> <span class="token comment" spellcheck="true">//存储key</span>
    <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>max <span class="token operator">&amp;&amp;</span> keys<span class="token punctuation">.</span>length <span class="token operator">></span> <span class="token function">parseInt</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>max<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span>#<span class="token number">123</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">// 如果超过最大缓存数</span>
    <span class="token comment" spellcheck="true">// 删除最早缓存的</span>
    <span class="token function">pruneCacheEntry</span><span class="token punctuation">(</span>cache<span class="token punctuation">,</span> keys<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">,</span> keys<span class="token punctuation">,</span> <span class="token keyword">this</span><span class="token punctuation">.</span>_vnode<span class="token punctuation">)</span>
<span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
<span class="token operator">&amp;</span>#<span class="token number">125</span><span class="token punctuation">;</span>
vnode<span class="token punctuation">.</span>data<span class="token punctuation">.</span>keepAlive <span class="token operator">=</span> <span class="token boolean">true</span> <span class="token comment" spellcheck="true">// 标记走了缓存</span></code></pre>
<h4 id="39-Vue-minxin的使用场景和原理？"><a href="#39-Vue-minxin的使用场景和原理？" class="headerlink" title="39.Vue.minxin的使用场景和原理？"></a>39.<code>Vue.minxin</code>的使用场景和原理？</h4><h3 id="核心答案：-6"><a href="#核心答案：-6" class="headerlink" title="核心答案："></a>核心答案：</h3><p>Vue.mixin 的作用就是抽离公共的业务逻辑，原理类似“对象的继承”，当组件初始化时会调用 mergeOptions 方法进行合并，采用策略模式针对不同的属性进行合并，如果混入的数据和本身组件中的数据冲突，会采用“就近原则”以组件的数据为准。</p>
<h3 id="补充回答："><a href="#补充回答：" class="headerlink" title="补充回答："></a>补充回答：</h3><p><code>mixin</code>中有很多缺陷“命名冲突问题”，“依赖问题”，“数据来源问题”，这里强调一下<code>mixin</code>的数据是不会被共享的。</p>
<h3 id="注意事项"><a href="#注意事项" class="headerlink" title="注意事项"></a>注意事项</h3><p>如果只是提取公用的数据或者通用的方法，并且这些数据或者方法，不需要组件间进行维护，就可以使用<code>mixins</code>。（类似于 js 中封装的一些公用的方法）</p>
<h4 id="40-mixins和vuex的区别"><a href="#40-mixins和vuex的区别" class="headerlink" title="40.mixins和vuex的区别?"></a>40.<code>mixins</code>和<code>vuex</code>的区别?</h4><p><code>vuex</code>公共状态管理，在一个组件被引入后，如果该组件改变了 vuex 里面的数据状态，其他引入 vuex 数据的组件也会对应修改，所有的 vue 组件应用的都是同一份 vuex 数据。（在 js 中，有点类似于浅拷贝）</p>
<p><code>vue</code>引入<code>mixins</code>数据，<code>mixins</code>数据或方法，在每一个组件中都是独立的，互不干扰的，都属于 vue 组件自身。（在 js 中，有点类似于深度拷贝）</p>
<h4 id="41-mixins和公共组件的区别"><a href="#41-mixins和公共组件的区别" class="headerlink" title="41.mixins和公共组件的区别?"></a>41.<code>mixins</code>和公共组件的区别?</h4><p>通用的数据和方法，确实可以提出一个通用的组件，由父子组件传参的形式进行分享公用。</p>
<h3 id="公共组件"><a href="#公共组件" class="headerlink" title="公共组件"></a>公共组件</h3><p>子组件通过 props 接收来自父组件（公共组件）的参数或者方法，但 vue 不建议，子组件直接修改 props 接收到的父组件的数据。需要在子组件的 data 中或者 computed 中定义一个字段来接收。（有点麻烦）<br>公共组件最主要的作用还是复用相同的 vue 组件（有视图，有方法，有状态<br>)。</p>
<h3 id="mixins"><a href="#mixins" class="headerlink" title="mixins"></a>mixins</h3><p>如果只是提取公用的数据或者通用的方法，并且这些数据或者方法，不需要组件间进行维护，就可以使用 mixins。（类似于 js 中封装的一些公用的方法）</p>
<h4 id="42-Vue-router有几种钩子函数？具体是什么及执行流程是怎样的？"><a href="#42-Vue-router有几种钩子函数？具体是什么及执行流程是怎样的？" class="headerlink" title="42.Vue-router有几种钩子函数？具体是什么及执行流程是怎样的？"></a>42.<code>Vue-router</code>有几种钩子函数？具体是什么及执行流程是怎样的？</h4><h3 id="核心答案：-7"><a href="#核心答案：-7" class="headerlink" title="核心答案："></a>核心答案：</h3><p>路由钩子的执行流程，钩子函数种类有：全局守卫、路由守卫、组件守卫。</p>
<h3 id="完整的导航解析流程"><a href="#完整的导航解析流程" class="headerlink" title="完整的导航解析流程"></a>完整的导航解析流程</h3><p><code>1.</code>导航被触发；</p>
<p><code>2.</code>在失活的组件里调用 beforeRouteLeave 守卫；</p>
<p><code>3.</code>调用全局 beforeEach 守卫；</p>
<p><code>4.</code>在复用组件里调用 beforeRouteUpdate 守卫；</p>
<p><code>5.</code>调用路由配置里的 beforeEnter 守卫；</p>
<p><code>6.</code>解析异步路由组件；</p>
<p><code>7.</code>在被激活的组件里调用 beforeRouteEnter 守卫；</p>
<p><code>8.</code>调用全局 beforeResolve 守卫；</p>
<p><code>9.</code>导航被确认；</p>
<p><code>10.</code>调用全局的 afterEach 钩子；</p>
<p><code>11.</code>DOM 更新；</p>
<p><code>12.</code>用创建好的实例调用 beforeRouteEnter 守卫中传给 next 的回调函数。</p>
<h4 id="43-vue-router-两种模式的区别？"><a href="#43-vue-router-两种模式的区别？" class="headerlink" title="43.vue-router 两种模式的区别？"></a>43.<code>vue-router</code> 两种模式的区别？</h4><h3 id="核心答案：-8"><a href="#核心答案：-8" class="headerlink" title="核心答案："></a>核心答案：</h3><p><code>vue-router</code> 有 3 种路由模式：<code>hash</code>、<code>history</code>、<code>abstract</code>。</p>
<ol>
<li><code>hash</code>模式：hash + hashChange</li>
</ol>
<p>特点：hash 虽然在 URL 中，但不被包括在 HTTP 请求中；用来指导浏览器动作，对服务端安全无用，hash 不会重加载页面。通过监听 hash（#）的变化来执行 js 代码 从而实现 页面的改变。</p>
<h3 id="核心代码："><a href="#核心代码：" class="headerlink" title="核心代码："></a>核心代码：</h3><pre class=" language-javaScript"><code class="language-javaScript">window.addEventListener(‘hashchange‘,function()&#123;
    self.urlChange()
&#125;)</code></pre>
<ol start="2">
<li><code>history</code>模式：historyApi + popState</li>
</ol>
<p><code>HTML5</code>推出的 history API，由 pushState()记录操作历史，监听 popstate 事件来监听到状态变更；<br>因为 只要刷新 这个 url（<a target="_blank" rel="noopener" href="http://www.ff.ff/jjkj/fdfd/fdf/fd%EF%BC%89%E5%B0%B1%E4%BC%9A%E8%AF%B7%E6%B1%82%E6%9C%8D%E5%8A%A1%E5%99%A8%EF%BC%8C%E7%84%B6%E8%80%8C%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%B8%8A%E6%A0%B9%E6%9C%AC%E6%B2%A1%E6%9C%89%E8%BF%99%E4%B8%AA%E8%B5%84%E6%BA%90%EF%BC%8C%E6%89%80%E4%BB%A5%E5%B0%B1%E4%BC%9A%E6%8A%A5404%EF%BC%8C%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88%E5%B0%B1">www.ff.ff/jjkj/fdfd/fdf/fd）就会请求服务器，然而服务器上根本没有这个资源，所以就会报404，解决方案就</a> 配置一下服务器端。</p>
<h4 id="说明："><a href="#说明：" class="headerlink" title="说明："></a>说明：</h4><p>1）<code>hash</code>: 使用 URL hash 值来作路由。支持所有浏览器，包括不支持 HTML5 History Api 的浏览器；</p>
<p>2）<code>history</code> : 依赖 HTML5 History API 和服务器配置。具体可以查看 HTML5 History 模式；</p>
<p>3）<code>abstract</code> : 支持所有 JavaScript 运行环境，如 Node.js 服务器端。如果发现没有浏览器的 API，路由会自动强制进入这个模式.</p>
<h4 id="44-Vue-为什么需要虚拟-DOM？-虚拟DOM的优劣如何？"><a href="#44-Vue-为什么需要虚拟-DOM？-虚拟DOM的优劣如何？" class="headerlink" title="44.Vue 为什么需要虚拟 DOM？ 虚拟DOM的优劣如何？"></a>44.<code>Vue</code> 为什么需要虚拟 DOM？ 虚拟<code>DOM</code>的优劣如何？</h4><h2 id="核心答案：-9"><a href="#核心答案：-9" class="headerlink" title="核心答案："></a>核心答案：</h2><p><code>Virtual DOM</code> 就是用 js 对象来描述真实 DOM，是对真实 DOM 的抽象，由于直接操作 DOM 性能低但是 js 层的操作效率高，可以将 DOM 操作转化成对象操作，最终通过 diff 算法比对差异进行更新 DOM (减少了对真实 DOM 的操作)。虚拟 DOM 不依赖真实平台环境从而也可以实现跨平台。</p>
<h2 id="补充回答：-1"><a href="#补充回答：-1" class="headerlink" title="补充回答："></a>补充回答：</h2><p><code>虚拟DOM</code>的实现就是普通对象包含 tag、data、hildren 等属性对真实节点的描述。（本质上就是在 JS 和 DOM 之间的一个缓存）</p>
<p><code>Vue2</code>的 Virtual DOM 借鉴了开源库 snabbdom 的实现。</p>
<p><code>VirtualDOM</code>映射到真实 DOM 要经历 VNode 的 create、diff、patch 等阶段。</p>
<h4 id="45-Vue中key的作用和工作原理，说说你对它的理解"><a href="#45-Vue中key的作用和工作原理，说说你对它的理解" class="headerlink" title="45.Vue中key的作用和工作原理，说说你对它的理解"></a>45.<code>Vue</code>中<code>key</code>的作用和工作原理，说说你对它的理解</h4><h3 id="核心答案：-10"><a href="#核心答案：-10" class="headerlink" title="核心答案："></a>核心答案：</h3><h4 id="例如："><a href="#例如：" class="headerlink" title="例如："></a>例如：</h4><pre class=" language-javaScript"><code class="language-javaScript">v-for="(item, index) in tableList" :key="index"</code></pre>
<p>key 的作用主要是为了高效的更新虚拟 DOM，其原理是 vue 在 patch 过程中通过 key 可以精准判断两个节点是否是同一个，从而避免频繁更新不同元素，使得整个 patch 过程更加高效，减少 DOM 操作量，提高性能。</p>
<h4 id="补充回答：-2"><a href="#补充回答：-2" class="headerlink" title="补充回答："></a>补充回答：</h4><ol>
<li><p>若不设置 key 还可能在列表更新时引发一些隐蔽的 bug</p>
</li>
<li><p>vue 中在使用相同标签名元素的过渡切换时，也会使用到 key 属性，其目的也是为了让 vue 可以区分它们，否则 vue 只会替换其内部属性而不会触发过渡效果。</p>
</li>
</ol>
<h4 id="46-说说-nextTick的使用"><a href="#46-说说-nextTick的使用" class="headerlink" title="46.说说$nextTick的使用?"></a>46.说说<code>$nextTick</code>的使用?</h4><ol>
<li><p><code>nextTick</code>的回调是在下次<code>DOM</code>更新循环结束之后执行的延迟回调。</p>
</li>
<li><p>在修改数据之后立即使用这个方法，获取更新后的<code>DOM</code>。</p>
</li>
<li><p><code>nextTick</code>主要使用了宏任务和微任务。</p>
</li>
</ol>
<h4 id="47-computed-和-watch-的区别和运用的场景？"><a href="#47-computed-和-watch-的区别和运用的场景？" class="headerlink" title="47.computed 和 watch 的区别和运用的场景？"></a>47.<code>computed</code> 和 <code>watch</code> 的区别和运用的场景？</h4><h3 id="核心答案：-11"><a href="#核心答案：-11" class="headerlink" title="核心答案："></a>核心答案：</h3><p><code>computed</code>：</p>
<p>计算属性。依赖其它属性值，并且 computed 的值有缓存，只有它依赖的属性值发生改变，下一次获取 computed 的值时才会重新计算 computed 的值；</p>
<p><code>watch</code>：</p>
<p>监听数据的变化。更多的是「观察」的作用，类似于某些数据的监听回调 ，每当监听的数据变化时都会执行回调进行后续操作；</p>
<h3 id="运用场景："><a href="#运用场景：" class="headerlink" title="运用场景："></a>运用场景：</h3><p>1）当我们需要进行数值计算，并且依赖于其它数据时，应该使用 computed，因为可以利用 computed 的缓存特性，避免每次获取值时，都要重新计算；</p>
<p>2）当我们需要在数据变化时执行异步或开销较大的操作时，应该使用 watch，使用 watch 选项允许我们执行异步操作 ( 访问一个 API )，限制我们执行该操作的频率，并在我们得到最终结果前，设置中间状态。</p>
<p>这些都是计算属性无法做到的。</p>
<h4 id="48-如何理解自定义指令？"><a href="#48-如何理解自定义指令？" class="headerlink" title="48.如何理解自定义指令？"></a>48.如何理解自定义指令？</h4><h4 id="核心答案：-12"><a href="#核心答案：-12" class="headerlink" title="核心答案："></a>核心答案：</h4><blockquote>
<p>指令的实现原理，可以从编译原理 =&gt;代码生成=&gt; 指令钩子实现进行概述</p>
</blockquote>
<p>1）在生成 ast 语法树时，遇到指令会给当前元素添加 directives 属性</p>
<p>2）通过 genDirectives 生成指令代码</p>
<p>3）在 patch 前将指令的钩子提取到 cbs 中，在 patch 过程中调用对应的钩子。</p>
<p>4）当执行指令对应钩子函数时，调用对应指令定义的方法</p>
<h4 id="49-router和-route的区别？"><a href="#49-router和-route的区别？" class="headerlink" title="49.$router和$route的区别？"></a>49.<code>$router</code>和<code>$route</code>的区别？</h4><p><code>this.$router</code>与<code>this.$route</code> 两者相差 一个 <code>r</code> 但是差距蛮大的。</p>
<p><code>Vue Router</code>是<code>Vue.js</code>的路由管理器，在 Vue 实例内部，可以通过<code>$router</code>访问路由实例</p>
<p>通过<code>$route</code>可以访问当前激活的路由的状态信息，包含了当前<code>URL</code>解析得到的信息，还有 URL 匹配到的路由记录，可以将<code>$router</code>理解为一个容器去管理了一组<code>$route</code>，</p>
<p>而<code>$route</code>是进行了当前 URL 和组件的映射。</p>
<h4 id="50-router对象有哪些属性？"><a href="#50-router对象有哪些属性？" class="headerlink" title="50.$router对象有哪些属性？"></a>50.<code>$router</code>对象有哪些属性？</h4><ul>
<li><p><code>$router.app</code>: 配置了 router 的 Vue 根实例。</p>
</li>
<li><p><code>$router.mode</code>: 路由使用的模式。</p>
</li>
<li><p><code>$router.currentRoute</code>: 当前路由对应的路由信息对象。</p>
</li>
</ul>
<h4 id="51-router对象有哪些方法？"><a href="#51-router对象有哪些方法？" class="headerlink" title="51.$router对象有哪些方法？"></a>51.<code>$router</code>对象有哪些方法？</h4><ul>
<li>$router.beforeEach(to, from, next)</li>
<li>$router.beforeResolve(to, from, next)</li>
<li>$router.afterEach(to, from)</li>
<li>$router.push(location[, onComplete[, onAbort]])</li>
<li>$router.replace(location[, onComplete[, onAbort]])</li>
<li>$router.go(n)</li>
<li>$router.back()$router.back</li>
<li>$history.forward()</li>
<li>$router.getMatchedComponents([location])</li>
<li>$router.resolve(location[, current[, append]])</li>
<li>$router.addRoutes(route)</li>
<li>$router.onReady(callback[, errorCallback])</li>
<li>$router.onError(callback)</li>
</ul>
<h3 id="52-route对象有哪些属性？"><a href="#52-route对象有哪些属性？" class="headerlink" title="52.$route对象有哪些属性？"></a>52.<code>$route</code>对象有哪些属性？</h3><ul>
<li><p><code>$route.path</code>:<br>返回字符串，对应当前路由的路径，总是解析为绝对路径。</p>
</li>
<li><p><code>$route.params</code>:<br>返回一个 key-value 对象，包含了动态片段和全匹配片段，如果没有路由参数，就是一个空对象。</p>
</li>
<li><p><code>$route.query</code>:<br>返回一个 key-value 对象，表示 URL 查询参数。</p>
</li>
<li><p><code>$route.hash</code>:<br>返回当前路由的带#的 hash 值，如果没有 hash 值，则为空字符串。</p>
</li>
<li><p><code>$route.fullPath</code>:<br>返回完成解析后的 URL，包含查询参数和 hash 的完整路径。</p>
</li>
<li><p><code>$route.matched</code>:<br>返回一个数组，包含当前路由的所有嵌套路径片段的路由记录，路由记录就是 routes 配置数组中的对象副本。</p>
</li>
<li><p><code>$route.name</code>:<br>如果存在当前路由名称则返回当前路由的名称。</p>
</li>
<li><p><code>$route.redirectedFrom</code>:<br>如果存在重定向，即为重定向来源的路由的名字。</p>
</li>
</ul>
<h4 id="53-对MVC-（react）-MVVM（vue）的了解"><a href="#53-对MVC-（react）-MVVM（vue）的了解" class="headerlink" title="53.对MVC （react） MVVM（vue）的了解?"></a>53.对<code>MVC （react）</code> <code>MVVM（vue）</code>的了解?</h4><h3 id="标签-腾讯-阿里-西门子"><a href="#标签-腾讯-阿里-西门子" class="headerlink" title="标签 腾讯 阿里 西门子"></a>标签 腾讯 阿里 西门子</h3><h3 id="什么是-MVC"><a href="#什么是-MVC" class="headerlink" title="什么是 MVC"></a>什么是 MVC</h3><ul>
<li><code>M（modal）</code>：是应用程序中处理数据逻辑的部分。</li>
<li><code>V （view）</code> ：是应用程序中数据显示的部分。</li>
<li><code>C（controller）</code>：是应用程序中处理用户交互的地方</li>
</ul>
<h3 id="什么是-MVVM"><a href="#什么是-MVVM" class="headerlink" title="什么是 MVVM"></a>什么是 MVVM</h3><ul>
<li>M（modal）：模型，定义数据结构。</li>
<li>C（controller）：实现业务逻辑，数据的增删改查。在 MVVM 模式中一般把 C 层算在 M 层中，（只有在理想的双向绑定模式下，Controller 才会完全的消失。这种理想状态一般不存在）。</li>
<li>VM（viewModal）：视图 View 的模型、映射和显示逻辑（如 if for 等，非业务逻辑），另外绑定器也在此层。ViewModel 是基于视图开发的一套模型，如果你的应用是给盲人用的，那么也可以开发一套基于 Audio 的模型 AudioModel。</li>
<li>V（view） ：将 ViewModel 通过特定的 GUI 展示出来，并在 GUI 控件上绑定视图交互事件，V(iew)一般由 MVVM 框架自动生成在浏览器中。</li>
</ul>
<h3 id="React-与-Vue-对比"><a href="#React-与-Vue-对比" class="headerlink" title="React 与 Vue 对比"></a>React 与 Vue 对比</h3><h3 id="相似点："><a href="#相似点：" class="headerlink" title="相似点："></a>相似点：</h3><ol>
<li>使用 Virtual DOM</li>
<li>提供了响应式 (Reactive) 和组件化 (Composable) 的视图组件。</li>
<li>将注意力集中保持在核心库，而将其他功能如路由和全局状态管理交给相关的库。</li>
</ol>
<h3 id="区别："><a href="#区别：" class="headerlink" title="区别："></a>区别：</h3><ol>
<li><p>在 React 应用中，当某个组件的状态发生变化时，它会以该组件为根，重新渲染整个组件子树。如要避免不必要的子组件的重渲染，你需要手动实现；在 Vue 应用中，组件的依赖是在渲染过程中自动追踪的，所以系统能精确知晓哪个组件确实需要被重渲染，开发者不需要考虑组件是否需要重新渲染之类的优化。</p>
</li>
<li><p>在 React 中，一切都是 JavaScript，所有的组件的渲染功能都依靠 JSX。JSX 是使用 XML 语法编写 JavaScript 的一种语法糖。你可以使用完整的编程语言 JavaScript 功能来构建你的视图页面；在 Vue 中有自带的渲染函数，Vue 也支持 JSX，Vue 官方推荐使用模板渲染视图。组件分为逻辑类组件和表现类组件。</p>
</li>
<li><p>组件作用域内的 CSS。CSS 作用域在 React 中是通过 CSS-in-JS 的方案实现的；在 Vue 中是通过给 style 标签加 scoped 标记实现的。</p>
</li>
<li><p>Vue 的路由库和状态管理库都是由官方维护支持且与核心库同步更新的。React 则是选择把这些问题交给社区维护，因此创建了一个更分散的生态系统。</p>
</li>
</ol>
<h3 id="54-Vue-js-如何让CSS只在当前组件中起作⽤"><a href="#54-Vue-js-如何让CSS只在当前组件中起作⽤" class="headerlink" title="54.Vue.js 如何让CSS只在当前组件中起作⽤?"></a>54.<code>Vue.js</code> 如何让<code>CSS</code>只在当前组件中起作⽤?</h3><p>将当前组件的 <code>&lt;style&gt;</code> 修改为 <code>&lt;style scoped&gt;</code></p>
<h4 id="55-Vue-中的diff原理"><a href="#55-Vue-中的diff原理" class="headerlink" title="55.Vue 中的diff原理?"></a>55.<code>Vue</code> 中的<code>diff</code>原理?</h4><h3 id="核心答案：-13"><a href="#核心答案：-13" class="headerlink" title="核心答案："></a>核心答案：</h3><p>vue 的 diff 算法是平级比较，不考虑跨级比较的情况。内部采用深度递归的方式 + 双指针的方式进行比较。</p>
<h3 id="补充回答：-3"><a href="#补充回答：-3" class="headerlink" title="补充回答："></a>补充回答：</h3><ol>
<li><p>先比较是否是相同节点</p>
</li>
<li><p>相同节点比较属性，并复用老节点</p>
</li>
<li><p>比较儿子节点，考虑老节点和新节点儿子的情况</p>
</li>
<li><p>优化比较：头头、尾尾、头尾、尾头</p>
</li>
<li><p>比对查找进行复用</p>
</li>
</ol>
<h3 id="Vue2-与-Vue3-x-的-diff-算法："><a href="#Vue2-与-Vue3-x-的-diff-算法：" class="headerlink" title="Vue2 与 Vue3.x 的 diff 算法："></a>Vue2 与 Vue3.x 的 diff 算法：</h3><p>Vue2 的核心 Diff 算法采用了双端比较的算法，同时从新旧 children 的两端开始进行比较，借助 key 值找到可复用的节点，再进行相关操作。</p>
<p>Vue3.x 借鉴了 ivi 算法和 inferno 算法，该算法中还运用了动态规划的思想求解最长递归子序列。(实际的实现可以结合 Vue3.x 源码看。)</p>
<h3 id="56-Vuex-的-5-个核心属性是什么？"><a href="#56-Vuex-的-5-个核心属性是什么？" class="headerlink" title="56.Vuex 的 5 个核心属性是什么？"></a>56.Vuex 的 5 个核心属性是什么？</h3><p>分别是 state、getters、mutations、actions、modules 。</p>
<h3 id="57-在-Vuex-中使用-mutation-要注意什么"><a href="#57-在-Vuex-中使用-mutation-要注意什么" class="headerlink" title="57.在 Vuex 中使用 mutation 要注意什么?"></a>57.在 Vuex 中使用 mutation 要注意什么?</h3><p>mutation 必须是同步函数</p>
<h3 id="58-Vuex-中-action-和-mutation-有什么相同点？"><a href="#58-Vuex-中-action-和-mutation-有什么相同点？" class="headerlink" title="58.Vuex 中 action 和 mutation 有什么相同点？"></a>58.Vuex 中 action 和 mutation 有什么相同点？</h3><p>第二参数都可以接收外部提交时传来的参数。</p>
<pre><code>this.$store.dispatch(&#39;ACTION_NAME&#39;,data)
和
this.$store.commit(&#39;SET_NUMBER&#39;,10)</code></pre>
<p>在组件中多次提交同一个 action，怎么写使用更方便。</p>
<h3 id="59-那为什么-new-Vue-里-data-可以是一个对象？"><a href="#59-那为什么-new-Vue-里-data-可以是一个对象？" class="headerlink" title="59.那为什么 new Vue 里 data 可以是一个对象？"></a>59.那为什么 new Vue 里 data 可以是一个对象？</h3><pre class=" language-javaScript"><code class="language-javaScript">new Vue(&#123;
  el: "#app",
  router,
  template: "<App/>",
  components: &#123; App &#125;,
&#125;);</code></pre>
<blockquote>
<p>原因：因为 JS 里的对象是引用关系，而且 new Vue 是不会被复用的，所以不存在引用对象的问题。</p>
</blockquote>
<h3 id="60-Vue-3-0-性能提升主要是通过哪几方面体现的？"><a href="#60-Vue-3-0-性能提升主要是通过哪几方面体现的？" class="headerlink" title="60.Vue 3.0 性能提升主要是通过哪几方面体现的？"></a>60.Vue 3.0 性能提升主要是通过哪几方面体现的？</h3><h3 id="1-响应式系统提升"><a href="#1-响应式系统提升" class="headerlink" title="1.响应式系统提升"></a>1.响应式系统提升</h3><p>vue2 在初始化的时候，对 data 中的每个属性使用 definepropery 调用 getter 和 setter 使之变为响应式对象。如果属性值为对象，还会递归调用 defineproperty 使之变为响应式对象。</p>
<p>vue3 使用 proxy 对象重写响应式。proxy 的性能本来比 defineproperty 好，proxy 可以拦截属性的访问、赋值、删除等操作，不需要初始化的时候遍历所有属性，另外有多层属性嵌套的话，只有访问某个属性的时候，才会递归处理下一级的属性。</p>
<h3 id="优势："><a href="#优势：" class="headerlink" title="优势："></a>优势：</h3><ul>
<li>可以监听动态新增的属性；</li>
<li>可以监听删除的属性 ；</li>
<li>可以监听数组的索引和 length 属性；</li>
</ul>
<h3 id="2-编译优化"><a href="#2-编译优化" class="headerlink" title="2. 编译优化"></a>2. 编译优化</h3><p>优化编译和重写虚拟 dom，让首次渲染和更新 dom 性能有更大的提升 vue2 通过标记静态根节点,优化 diff 算法 vue3 标记和提升所有静态根节点,diff 的时候只比较动态节点内容</p>
<p>Fragments, 模板里面不用创建唯一根节点,可以直接放同级标签和文本内容</p>
<h3 id="静态提升"><a href="#静态提升" class="headerlink" title="静态提升"></a>静态提升</h3><p>patch flag, 跳过静态节点,直接对比动态节点,缓存事件处理函数</p>
<h3 id="3-源码体积的优化"><a href="#3-源码体积的优化" class="headerlink" title="3. 源码体积的优化"></a>3. 源码体积的优化</h3><p>vue3 移除了一些不常用的 api，例如：inline-template、filter 等 使用 tree-shaking</p>
<h3 id="61-Composition-Api-与-Vue-2-x-使用的-Options-Api-有什么区别？"><a href="#61-Composition-Api-与-Vue-2-x-使用的-Options-Api-有什么区别？" class="headerlink" title="61.Composition Api 与 Vue 2.x 使用的 Options Api 有什么区别？"></a>61.Composition Api 与 Vue 2.x 使用的 Options Api 有什么区别？</h3><h3 id="Options-Api"><a href="#Options-Api" class="headerlink" title="Options Api"></a>Options Api</h3><p>包含一个描述组件选项（data、methods、props 等）的对象 options；</p>
<p>API 开发复杂组件，同一个功能逻辑的代码被拆分到不同选项 ；</p>
<p>使用 mixin 重用公用代码，也有问题：命名冲突，数据来源不清晰；</p>
<h3 id="composition-Api"><a href="#composition-Api" class="headerlink" title="composition Api"></a>composition Api</h3><p>vue3 新增的一组 api，它是基于函数的 api，可以更灵活的组织组件的逻辑。</p>
<p>解决 options api 在大型项目中，options api 不好拆分和重用的问题。</p>
<h3 id="62-Proxy-相对于-Object-defineProperty-区别？"><a href="#62-Proxy-相对于-Object-defineProperty-区别？" class="headerlink" title="62.Proxy 相对于 Object.defineProperty 区别？"></a>62.Proxy 相对于 Object.defineProperty 区别？</h3><p>有哪些优点？</p>
<p>proxy 的性能本来比 defineproperty 好，proxy 可以拦截属性的访问、赋值、删除等操作，不需要初始化的时候遍历所有属性，另外有多层属性嵌套的话，只有访问某个属性的时候，才会递归处理下一级的属性。</p>
<ul>
<li>可以* 监听数组变化</li>
<li>可以劫持整个对象</li>
<li>操作时不是对原对象操作,是 new Proxy 返回的一个新对象</li>
<li>可以劫持的操作有 13 种</li>
</ul>
<h3 id="63-Vue-3-0-在编译方面有哪些优化？"><a href="#63-Vue-3-0-在编译方面有哪些优化？" class="headerlink" title="63.Vue 3.0 在编译方面有哪些优化？"></a>63.Vue 3.0 在编译方面有哪些优化？</h3><p>vue.js 3.x 中标记和提升所有的静态节点，diff 的时候只需要对比动态节点内容；</p>
<p>Fragments（升级 vetur 插件):<br>template 中不需要唯一根节点，可以直接放文本或者同级标签</p>
<p>静态提升(hoistStatic),当使用 hoistStatic 时,所有静态的节点都被提升到 render 方法之外.只会在应用启动的时候被创建一次,之后使用只需要应用提取的静态节点，随着每次的渲染被不停的复用。</p>
<p>patch flag, 在动态标签末尾加上相应的标记,只能带 patchFlag 的节点才被认为是动态的元素,会被追踪属性的修改,能快速的找到动态节点,而不用逐个逐层遍历，提高了虚拟 dom diff 的性能。</p>
<p>缓存事件处理函数 cacheHandler,避免每次触发都要重新生成全新的 function 去更新之前的函数 tree shaking 通过摇树优化核心库体积,减少不必要的代码量</p>
<h3 id="64-Vue-js-3-0-响应式系统的实现原理？"><a href="#64-Vue-js-3-0-响应式系统的实现原理？" class="headerlink" title="64.Vue.js 3.0 响应式系统的实现原理？"></a>64.Vue.js 3.0 响应式系统的实现原理？</h3><h3 id="1-reactive"><a href="#1-reactive" class="headerlink" title="1. reactive"></a>1. reactive</h3><p>设置对象为响应式对象。接收一个参数，判断这参数是否是对象。不是对象则直接返回这个参数，不做响应式处理。创建拦截器 handerler，设置 get/set/deleteproperty。</p>
<h4 id="get"><a href="#get" class="headerlink" title="get"></a>get</h4><p>收集依赖（track）；<br>如果当前 key 的值是对象，则为当前 key 的对<br>象创建拦截器 handler, 设置 get/set/deleteProperty；<br>如果当前的 key 的值不是对象，则返回当前 key 的值。</p>
<h4 id="set"><a href="#set" class="headerlink" title="set"></a>set</h4><p>设置的新值和老值不相等时，更新为新值，并触发更新（trigger）。</p>
<p>deleteProperty 当前对象有这个 key 的时候，删除这个 key 并触发更新（trigger）。</p>
<h3 id="2-effect"><a href="#2-effect" class="headerlink" title="2. effect"></a>2. effect</h3><p>接收一个函数作为参数。作用是：访问响应式对象属性时去收集依赖</p>
<h3 id="3-track"><a href="#3-track" class="headerlink" title="3. track"></a>3. track</h3><p>接收两个参数：target 和 key<br>－如果没有 activeEffect，则说明没有创建 effect 依赖</p>
<p>－如果有 activeEffect，则去判断 WeakMap 集合中是否有 target 属性</p>
<p>－WeakMap 集合中没有 target 属性，则 set(target, (depsMap = new Map()))</p>
<p>－WeakMap 集合中有 target 属性，则判断 target 属性的 map 值的 depsMap 中是否有 key 属性</p>
<p>－depsMap 中没有 key 属性，则 set(key, (dep = new Set())) －depsMap 中有 key 属性，则添加这个 activeEffect</p>
<h3 id="4-trigger"><a href="#4-trigger" class="headerlink" title="4. trigger"></a>4. trigger</h3><p>判断 WeakMap 中是否有 target 属性，WeakMap 中有 target 属性，则判断 target 属性的 map 值中是否有 key 属性，有的话循环触发收集的 effect()。</p>

                
            </div>
            <hr/>

            



            <div class="tag_share" style="display: block;">
                <div class="post-meta__tag-list" style="display: inline-block;">
                    
                        <div class="article-tag">
                            
                                <a href="/pride-blog/tags/%E6%AF%8F%E5%A4%A9%E4%B8%80%E4%B8%AA%E7%A6%BB%E8%81%8C%E5%B0%8F%E6%8A%80%E5%B7%A7/">
                                    <span class="chip bg-color">每天一个离职小技巧</span>
                                </a>
                            
                        </div>
                    
                </div>
                <div class="post_share" style="zoom: 80%; width: fit-content; display: inline-block; float: right; margin: -0.15rem 0;">
                    <link rel="stylesheet" type="text/css" href="/pride-blog/libs/share/css/share.min.css">
<div id="article-share">

    

    

</div>

                </div>
            </div>
            
        </div>
    </div>

    

    

    

    

    

    

    

    

    

<article id="prenext-posts" class="prev-next articles">
    <div class="row article-row">
        
        <div class="article col s12 m6" data-aos="fade-up">
            <div class="article-badge left-badge text-color">
                <i class="fas fa-chevron-left"></i>&nbsp;上一篇</div>
            <div class="card">
                <a href="/pride-blog/2021/080527948.html">
                    <div class="card-image">
                        
                        
                        <img src="/pride-blog/medias/featureimages/14.jpg" class="responsive-img" alt="Vue源码系列6-编译器的解析">
                        
                        <span class="card-title">Vue源码系列6-编译器的解析</span>
                    </div>
                </a>
                <div class="card-content article-content">
                    <div class="summary block-with-text">
                        
                            
                        
                    </div>
                    <div class="publish-info">
                        <span class="publish-date">
                            <i class="far fa-clock fa-fw icon-date"></i>2021-08-05
                        </span>
                        <span class="publish-author">
                            
                            <i class="fas fa-bookmark fa-fw icon-category"></i>
                            
                            <a href="/pride-blog/categories/Vue%E6%BA%90%E7%A0%81/" class="post-category">
                                    Vue源码
                                </a>
                            
                            
                        </span>
                    </div>
                </div>
                
                <div class="card-action article-tags">
                    
                    <a href="/pride-blog/tags/Vue%E6%BA%90%E7%A0%81/">
                        <span class="chip bg-color">Vue源码</span>
                    </a>
                    
                </div>
                
            </div>
        </div>
        
        
        <div class="article col s12 m6" data-aos="fade-up">
            <div class="article-badge right-badge text-color">
                下一篇&nbsp;<i class="fas fa-chevron-right"></i>
            </div>
            <div class="card">
                <a href="/pride-blog/2021/080441516.html">
                    <div class="card-image">
                        
                        
                        <img src="/pride-blog/medias/featureimages/3.jpg" class="responsive-img" alt="javaScript">
                        
                        <span class="card-title">javaScript</span>
                    </div>
                </a>
                <div class="card-content article-content">
                    <div class="summary block-with-text">
                        
                            
                        
                    </div>
                    <div class="publish-info">
                            <span class="publish-date">
                                <i class="far fa-clock fa-fw icon-date"></i>2021-08-04
                            </span>
                        <span class="publish-author">
                            
                            <i class="fas fa-bookmark fa-fw icon-category"></i>
                            
                            <a href="/pride-blog/categories/%E6%AF%8F%E5%A4%A9%E4%B8%80%E4%B8%AA%E7%A6%BB%E8%81%8C%E5%B0%8F%E6%8A%80%E5%B7%A7/" class="post-category">
                                    每天一个离职小技巧
                                </a>
                            
                            
                        </span>
                    </div>
                </div>
                
                <div class="card-action article-tags">
                    
                    <a href="/pride-blog/tags/%E6%AF%8F%E5%A4%A9%E4%B8%80%E4%B8%AA%E7%A6%BB%E8%81%8C%E5%B0%8F%E6%8A%80%E5%B7%A7/">
                        <span class="chip bg-color">每天一个离职小技巧</span>
                    </a>
                    
                </div>
                
            </div>
        </div>
        
    </div>
</article>

</div>



<!-- 代码块功能依赖 -->
<script type="text/javascript" src="/pride-blog/libs/codeBlock/codeBlockFuction.js"></script>

<!-- 代码语言 -->

<script type="text/javascript" src="/pride-blog/libs/codeBlock/codeLang.js"></script>


<!-- 代码块复制 -->

<script type="text/javascript" src="/pride-blog/libs/codeBlock/codeCopy.js"></script>


<!-- 代码块收缩 -->

<script type="text/javascript" src="/pride-blog/libs/codeBlock/codeShrink.js"></script>


    </div>
    <div id="toc-aside" class="expanded col l3 hide-on-med-and-down">
        <div class="toc-widget card" style="background-color: white;">
            <div class="toc-title"><i class="far fa-list-alt"></i>&nbsp;&nbsp;目录</div>
            <div id="toc-content"></div>
        </div>
    </div>
</div>

<!-- TOC 悬浮按钮. -->

<div id="floating-toc-btn" class="hide-on-med-and-down">
    <a class="btn-floating btn-large bg-color">
        <i class="fas fa-list-ul"></i>
    </a>
</div>


<script src="/pride-blog/libs/tocbot/tocbot.min.js"></script>
<script>
    $(function () {
        tocbot.init({
            tocSelector: '#toc-content',
            contentSelector: '#articleContent',
            headingsOffset: -($(window).height() * 0.4 - 45),
            collapseDepth: Number('0'),
            headingSelector: 'h2, h3, h4'
        });

        // modify the toc link href to support Chinese.
        let i = 0;
        let tocHeading = 'toc-heading-';
        $('#toc-content a').each(function () {
            $(this).attr('href', '#' + tocHeading + (++i));
        });

        // modify the heading title id to support Chinese.
        i = 0;
        $('#articleContent').children('h2, h3, h4').each(function () {
            $(this).attr('id', tocHeading + (++i));
        });

        // Set scroll toc fixed.
        let tocHeight = parseInt($(window).height() * 0.4 - 64);
        let $tocWidget = $('.toc-widget');
        $(window).scroll(function () {
            let scroll = $(window).scrollTop();
            /* add post toc fixed. */
            if (scroll > tocHeight) {
                $tocWidget.addClass('toc-fixed');
            } else {
                $tocWidget.removeClass('toc-fixed');
            }
        });

        
        /* 修复文章卡片 div 的宽度. */
        let fixPostCardWidth = function (srcId, targetId) {
            let srcDiv = $('#' + srcId);
            if (srcDiv.length === 0) {
                return;
            }

            let w = srcDiv.width();
            if (w >= 450) {
                w = w + 21;
            } else if (w >= 350 && w < 450) {
                w = w + 18;
            } else if (w >= 300 && w < 350) {
                w = w + 16;
            } else {
                w = w + 14;
            }
            $('#' + targetId).width(w);
        };

        // 切换TOC目录展开收缩的相关操作.
        const expandedClass = 'expanded';
        let $tocAside = $('#toc-aside');
        let $mainContent = $('#main-content');
        $('#floating-toc-btn .btn-floating').click(function () {
            if ($tocAside.hasClass(expandedClass)) {
                $tocAside.removeClass(expandedClass).hide();
                $mainContent.removeClass('l9');
            } else {
                $tocAside.addClass(expandedClass).show();
                $mainContent.addClass('l9');
            }
            fixPostCardWidth('artDetail', 'prenext-posts');
        });
        
    });
</script>

    

</main>




    <footer class="page-footer bg-color">
    

    <div class="container row center-align"
         style="margin-bottom: 0px !important;">
        <div class="col s12 m8 l8 copy-right">
            Copyright&nbsp;&copy;
            
                <span id="year">2021-2023</span>
            
            <span id="year">2021</span>
            <a href="/pride-blog/about" target="_blank">zihao xiong</a>
            |&nbsp;Powered by&nbsp;<a href="https://hexo.io/" target="_blank">Hexo</a>
            |&nbsp;Theme&nbsp;<a href="https://github.com/blinkfox/hexo-theme-matery" target="_blank">Matery</a>
            <br>
            
            
            
            
            
            <br>

            <!-- 运行天数提醒. -->
            
            <br>
            
        </div>
        <div class="col s12 m4 l4 social-link ">














</div>
    </div>
</footer>

<div class="progress-bar"></div>


    <!-- 搜索遮罩框 -->
<div id="searchModal" class="modal">
    <div class="modal-content">
        <div class="search-header">
            <span class="title"><i class="fas fa-search"></i>&nbsp;&nbsp;搜索</span>
            <input type="search" id="searchInput" name="s" placeholder="请输入搜索的关键字"
                   class="search-input">
        </div>
        <div id="searchResult"></div>
    </div>
</div>

<script type="text/javascript">
$(function () {
    var searchFunc = function (path, search_id, content_id) {
        'use strict';
        $.ajax({
            url: path,
            dataType: "xml",
            success: function (xmlResponse) {
                // get the contents from search data
                var datas = $("entry", xmlResponse).map(function () {
                    return {
                        title: $("title", this).text(),
                        content: $("content", this).text(),
                        url: $("url", this).text()
                    };
                }).get();
                var $input = document.getElementById(search_id);
                var $resultContent = document.getElementById(content_id);
                $input.addEventListener('input', function () {
                    var str = '<ul class=\"search-result-list\">';
                    var keywords = this.value.trim().toLowerCase().split(/[\s\-]+/);
                    $resultContent.innerHTML = "";
                    if (this.value.trim().length <= 0) {
                        return;
                    }
                    // perform local searching
                    datas.forEach(function (data) {
                        var isMatch = true;
                        var data_title = data.title.trim().toLowerCase();
                        var data_content = data.content.trim().replace(/<[^>]+>/g, "").toLowerCase();
                        var data_url = data.url;
                        data_url = data_url.indexOf('/') === 0 ? data.url : '/' + data_url;
                        var index_title = -1;
                        var index_content = -1;
                        var first_occur = -1;
                        // only match artiles with not empty titles and contents
                        if (data_title !== '' && data_content !== '') {
                            keywords.forEach(function (keyword, i) {
                                index_title = data_title.indexOf(keyword);
                                index_content = data_content.indexOf(keyword);
                                if (index_title < 0 && index_content < 0) {
                                    isMatch = false;
                                } else {
                                    if (index_content < 0) {
                                        index_content = 0;
                                    }
                                    if (i === 0) {
                                        first_occur = index_content;
                                    }
                                }
                            });
                        }
                        // show search results
                        if (isMatch) {
                            str += "<li><a href='" + data_url + "' class='search-result-title'>" + data_title + "</a>";
                            var content = data.content.trim().replace(/<[^>]+>/g, "");
                            if (first_occur >= 0) {
                                // cut out 100 characters
                                var start = first_occur - 20;
                                var end = first_occur + 80;
                                if (start < 0) {
                                    start = 0;
                                }
                                if (start === 0) {
                                    end = 100;
                                }
                                if (end > content.length) {
                                    end = content.length;
                                }
                                var match_content = content.substr(start, end);
                                // highlight all keywords
                                keywords.forEach(function (keyword) {
                                    var regS = new RegExp(keyword, "gi");
                                    match_content = match_content.replace(regS, "<em class=\"search-keyword\">" + keyword + "</em>");
                                });

                                str += "<p class=\"search-result\">" + match_content + "...</p>"
                            }
                            str += "</li>";
                        }
                    });
                    str += "</ul>";
                    $resultContent.innerHTML = str;
                });
            }
        });
    };

    searchFunc('/pride-blog/search.xml', 'searchInput', 'searchResult');
});
</script>

    <!-- 回到顶部按钮 -->
<div id="backTop" class="top-scroll">
    <a class="btn-floating btn-large waves-effect waves-light" href="#!">
        <i class="fas fa-arrow-up"></i>
    </a>
</div>


    <script src="/pride-blog/libs/materialize/materialize.min.js"></script>
    <script src="/pride-blog/libs/masonry/masonry.pkgd.min.js"></script>
    <script src="/pride-blog/libs/aos/aos.js"></script>
    <script src="/pride-blog/libs/scrollprogress/scrollProgress.min.js"></script>
    <script src="/pride-blog/libs/lightGallery/js/lightgallery-all.min.js"></script>
    <script src="/pride-blog/js/matery.js"></script>

    <!-- Baidu Analytics -->

    <!-- Baidu Push -->

<script>
    (function () {
        var bp = document.createElement('script');
        var curProtocol = window.location.protocol.split(':')[0];
        if (curProtocol === 'https') {
            bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
        } else {
            bp.src = 'http://push.zhanzhang.baidu.com/push.js';
        }
        var s = document.getElementsByTagName("script")[0];
        s.parentNode.insertBefore(bp, s);
    })();
</script>

    
    <script src="/pride-blog/libs/others/clicklove.js" async="async"></script>
    
    

    

    

    <!--腾讯兔小巢-->
    
    
    <script type="text/javascript" color="0,0,255"
        pointColor="0,0,255" opacity='0.7'
        zIndex="-1" count="99"
        src="/pride-blog/libs/background/canvas-nest.js"></script>
    

    
    
    <script type="text/javascript" size="150" alpha='0.6'
        zIndex="-1" src="/pride-blog/libs/background/ribbon-refresh.min.js" async="async"></script>
    

    
    <script type="text/javascript" src="/pride-blog/libs/background/ribbon-dynamic.js" async="async"></script>
    

    
    <script src="/pride-blog/libs/instantpage/instantpage.js" type="module"></script><!-- hexo-inject:begin --><!-- hexo-inject:end -->
    

</body>
<script src="./../source/js/cursor.js"></script>

</html>
